循环数组(circular array) ,ArrayDeque 是非线程安全的,当多个线程同时使用的时候,需要手动同步;而且,该容器不允许放入null元素。
用于表示 栈和队列
1 底层数据结构
对象数组,head指向第一个有效元素 ,tail指向第一个可以插入的空位。
transient Object[] elements; // non-private to simplify nested class access
transient int head;
transient int tail;
2 构造方法
- ArrayDeque() 初始化大小为 16 的数组
- ArrayDeque(int numElements) 初始化数组,大小为 大于等于 numElements 的 2 的指数倍 的最小值,最小为 8 .
- ArrayDeque(Collection<? extends E> c) 初始化数组,大小为 大于等于 c.size() 的 2 的指数倍的最小值,最小为 8, 然后添加 c 中元素。
public ArrayDeque() {
elements = new Object[16];
}
public ArrayDeque(int numElements) {
allocateElements(numElements);
}
public ArrayDeque(Collection<? extends E> c) {
allocateElements(c.size());
addAll(c);
}
private void allocateElements(int numElements) {
elements = new Object[calculateSize(numElements)];
}
private void allocateElements(int numElements) {
elements = new Object[calculateSize(numElements)];
}
//
private static int calculateSize(int numElements) {
int initialCapacity = MIN_INITIAL_CAPACITY;
// Find the best power of two to hold elements.
// Tests "<=" because arrays aren't kept full.
if (numElements >= initialCapacity) {
initialCapacity = numElements;
initialCapacity |= (initialCapacity >>> 1);
initialCapacity |= (initialCapacity >>> 2);
initialCapacity |= (initialCapacity >>> 4);
initialCapacity |= (initialCapacity >>> 8);
initialCapacity |= (initialCapacity >>> 16);
initialCapacity++;
if (initialCapacity < 0) // Too many elements, must back off
initialCapacity >>>= 1;// Good luck allocating 2 ^ 30 elements
}
return initialCapacity;
}
3 添加方法
- addFirst(E e) 在首端插入元素,即在
head的前面插入元素,空间不够则 调用 doubleCapacity 方法扩容 2 倍。
这里 head = (head - 1) & (elements.length - 1) ,由于 elements.length 是 2 的指数倍, elements.length - 1 的地位全是 1 . 此时进行 & 运算,相当于对其取模。
public void addFirst(E e) {
if (e == null)
throw new NullPointerException();
elements[head = (head - 1) & (elements.length - 1)] = e;
if (head == tail)
doubleCapacity();
}
- addLast(E e) 在尾端插入元素,即在
tail的位置插入元素。插入完成后再检查空间,如果空间已经用光,则调用 doubleCapacity 扩容。
public void addLast(E e) {
if (e == null)
throw new NullPointerException();
elements[tail] = e;
if ( (tail = (tail + 1) & (elements.length - 1)) == head)
doubleCapacity();
}
4 删除方法
- removeFirst()
- removeLast()
5 删除并返回
- pollFirst()
- pollLast()
6 获取方法
- getFirst() 非null,是null值报错。
- getLast() null报错。
- peekFirst() 也是获取head元素,可以为 null,表示空数组。
- peekLast() 也是获取尾元素tail-1,可以为 null,表示空数组。
7 删除指定对象
- removeFirstOccurrence(Object o)
- removeLastOccurrence(Object o)