ArrayDeque
双端队列,表示能够添加元素到(或删除,获取)队列头也能够添加元素到(或删除,获取)队列尾java
类中定义成员变量,一个数组和两个int数组
transient Object[] elements; transient int head; transient int tail;
数据结构比较清晰,就是一个数组,head指向队列的头,tail指向队列的尾数据结构
数组定义要求数组的容量为2的n次幂设计
先看删除逻辑,由于比较简单,实现以下code
public E poll() { if (size == 0) // 队列为空 return null; int s = --size; modCount++; // 数组中第一个为队列头 E result = (E) queue[0]; E x = (E) queue[s]; queue[s] = null; if (s != 0) // 队列非空时,重排剩下的元素 siftDown(0, x); return result; }
在队头和队尾添加的逻辑基本一致,这里以在队列尾添加元素绩进行分析对象
public void addLast(E e) { if (e == null) // 不支持向队列中塞入null对象 throw new NullPointerException(); elements[tail] = e; if ( (tail = (tail + 1) & (elements.length - 1)) == head) { // tail 后移一位,若tail长度超过数组长度,则tail转到数组头 // 上面的与操做等价于对数组长度进行求余 // 若tail和head相等,则表示数组内容填充满,须要扩容 doubleCapacity(); } } // 数组扩容方法 private void doubleCapacity() { assert head == tail; int p = head; int n = elements.length; int r = n - p; // number of elements to the right of p // 新的容量为原来的两倍 int newCapacity = n << 1; if (newCapacity < 0) // int逸出判断 throw new IllegalStateException("Sorry, deque too big"); Object[] a = new Object[newCapacity]; System.arraycopy(elements, p, a, 0, r); System.arraycopy(elements, 0, a, r, p); elements = a; head = 0; tail = n; }
下面是一个数组扩容的逻辑示意图索引
1 -> 9 -> 5 -> 7 -> 4 -> 3 -> 5 -> 8
以弹出队头的元素为例,会直接返回队列头的元素,并将head前移一位,并将数组中源队列头的数据清掉(赋值为null)接口
public E pollFirst() { int h = head; @SuppressWarnings("unchecked") E result = (E) elements[h]; // Element is null if deque empty if (result == null) return null; elements[h] = null; // Must null out slot head = (h + 1) & (elements.length - 1); return result; }
删除元素的示意图以下队列