Queue
Queue接口继承自Collection接口,扩展方法有6个,一组是抛出异常的实现,另外一组是返回值的实现(没有则返回null)。
| 抛异常 | 返回值 | |
|---|---|---|
| 插入 | add(e) | offer(E e) |
| 删除 | remove() | poll() |
| 查询 | element() | peek() |
Deque(双向队列)
Deque 接口继承之 Queue,扩展方法有12个
| 头部操作 | 尾部操作 | ||||
|---|---|---|---|---|---|
| 抛异常 | 返回值 | 抛异常 | 返回值 | ||
| 插入 | addFirst(e) | offerFirst(e) | addLast(e) | offerLast(e) | |
| 删除 | removeFirst() | pollFirst() | removeLast() | pollLast() | |
| 查询 | getFirst() | peekFirst() | getLast() | peekLast() |
ArrayDeque
ArrayDeque 一种双端队列实现。它继承自 AbstractCollection 类并实现了 Deque 接口,提供了高效的插入和删除操作
ArrayDeque和LinkedList是Deque的两个通用实现,官方更推荐使用AarryDeque用作栈和队列
数据结构
ArrayDeque 内部使用一个循环数组作为底层数据结构。数组的长度会根据实际元素数量进行动态调整,以实现高效的插入和删除操作。
首先,我们来看一下 ArrayDeque 的主要成员变量:
//存储元素的数组
transient Object[] elements;
//指向队列头部元素的索引
transient int head;
//指向队列尾部元素的索引
transient int tail;
head 和 tail 变量的值会根据插入和删除操作进行调整,以维护队列的双端特性。
扩容机制
当队列的元素数量达到了数组长度时,会触发扩容操作。下面是 ArrayDeque 的扩容过程:
- 创建一个新的数组,长度为原数组的两倍,并将原数组中的元素按顺序复制到新数组中。
- 调整新数组的 head 和 tail 索引,使其指向正确的位置。
//ArrayDeque 默认容量为 16
//当 last == head 时,进行扩容一倍
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)
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;
}