ArrayDeque简介说明
下文笔者讲述ArrayDeque简介说明
ArrayDeque简介
ArrayDeque是Deque接口的一种实现 依赖于可变数组来实现的 ArrayDeque没有容量限制,可根据需求自动进行扩容 ArrayDeque可作为栈来使用,效率要高于Stack ArrayDeque可以作为队列来使用,效率相较于基于双向链表的Linkedlist也要更好一些
ArrayDeque的成员变量
//数组存储元素 transient Object[] elements; //头部元素索引 transient int head; //尾部元素索引 transient int tail; //最小容量 private static final int MIN_INITIAL_CAPACITY = 8;
ArrayDeque底层使用数组存储元素 同时还使用head和tail来表示索引 但注意tail不是尾部元素的索引 而是尾部元素的下一位 即下一个将要被加入的元素的索引
ArrayDeque如何初始化
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) {
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
}
elements = new Object[initialCapacity];
}
ArrayDeque的初始化容量必须是2^n 你传的初始化容量如果是10 那么实际申请的数组容量是16 如果申请的容量是33,那么实际的容量是62 如果申请的容量是62,那么实际申请的容量是128。 我们可以从allocateElements方法中看出以上的运行原理
ArrayDeque中add方法
public void addFirst(E e) {
if (e == null)
throw new NullPointerException();
elements[head = (head - 1) & (elements.length - 1)] = e;
if (head == tail)
doubleCapacity();
}
public void addLast(E e) {
if (e == null)
throw new NullPointerException();
//tail中保存的是即将加入末尾的元素的索引
elements[tail] = e;
//tail向后移动一位
if ( (tail = (tail + 1) & (elements.length - 1)) == head)
//tail和head相遇,空间用尽,需要扩容
doubleCapacity();
}
注意事项:
tail的计算公式(tail = (tail + 1) & (elements.length - 1))
当tail到达容量最后一个的时候,tail就为等于0,否则tail的值tail+1
ArrayDeque扩容机制
private void doubleCapacity() {
assert head == tail; //扩容时头部索引和尾部索引肯定相等
int p = head;
int n = elements.length;
//头部索引到数组末端(length-1处)共有多少元素
int r = n - p; // number of elements to the right of p
//容量翻倍
int newCapacity = n << 1;
//容量过大,溢出了
if (newCapacity < 0)
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;
}
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。


