public interface Queue<E> extends Collection<E> { // 增加一个元素到队尾,如果队列已满,则抛出一个IIIegaISlabEepeplian异常 boolean add(E e); // 添加一个元素到队尾并返回true,如果队列已满,则返回false boolean offer(E e); // 移除并返回队列头部的元素,如果队列为空,则抛出一个NoSuchElementException异常 E remove(); // 移除并返问队列头部的元素,如果队列为空,则返回null E poll(); // 返回队列头部的元素,如果队列为空,则抛出一个NoSuchElementException异常 E element(); // 返问队列头部的元素,如果队列为空,则返回null E peek(); }
看到Queue的定义,有没有发现它和Stack的方法是非常相似的。
但是ArrayDeque并不是一个固定大小的队列,每次队列满了就会进行扩容,除非扩容至超过int的边界,才会抛出异常。所以这里的add和offer几乎是没有区别的。
2.底层存储
当然从ArrayDeque的命名就可以看出他的底层是用数组实现的(而LinkedList则是用链表实现的队列),来主要看一下ArrayDeque。
// 底层用数组存储元素 private transient E[] elements; // 队列的头部元素索引(即将pop出的一个) private transient int head; // 队列下一个要添加的元素索引 private transient int tail; // 最小的初始化容量大小,需要为2的n次幂 private static final int MIN_INITIAL_CAPACITY = 8;
这里需要注意的是MIN_INITIAL_CAPACITY,这个初始化容量必须为2的n次幂。为什么必须要是2的n次幂呢,还记得HashMap中我们的分析吗,HashMap也要求其底层数组的初始容量必须为2的n次幂,还记得当时是基于什么原因吗?不记得话,那就返回去看一下《 给jdk写注释系列之jdk1.6容器(4)-HashMap源码解析 》。那么ArrayDeque这里又是基于什么考虑呢,我们下面再看。
而tail不是最后一个元素的索引,是下一个要添加的元素索引,也就是最后一个元素+1。
3.构造方法