1. 概述
本文将深入讲解 Java 中的 ArrayDeque
类——它是 Deque
接口的一个实现。
ArrayDeque
(全称 "Array Double Ended Queue",读作 "ArrayDeck")是一种特殊的可扩展数组,允许我们在两端高效地添加或删除元素。
ArrayDeque
实现既可作为 栈(Stack,后进先出) 使用,也可作为 队列(Queue,先进先出) 使用。
2. API 快速一览
对于每种操作,我们都有两种方法可选:
- ❌ 抛异常组:操作失败时抛出异常
- ✅ 状态返回组:操作失败时返回状态或特殊值
操作 | 状态返回方法 | 抛异常方法 |
---|---|---|
头部插入 | offerFirst(e) |
addFirst(e) |
头部移除 | pollFirst() |
removeFirst() |
头部获取 | peekFirst() |
getFirst() |
尾部插入 | offerLast(e) |
addLast(e) |
尾部移除 | pollLast() |
removeLast() |
尾部获取 | peekLast() |
getLast() |
3. 方法使用实践
下面通过几个简单示例展示 ArrayDeque
的实际用法。
3.1 用作栈(Stack)
先看如何将 ArrayDeque
当作栈使用,压入元素:
@Test
public void whenPush_addsAtFirst() {
Deque<String> stack = new ArrayDeque<>();
stack.push("first");
stack.push("second");
assertEquals("second", stack.getFirst());
}
再演示弹出元素的操作:
@Test
public void whenPop_removesLast() {
Deque<String> stack = new ArrayDeque<>();
stack.push("first");
stack.push("second");
assertEquals("second", stack.pop());
}
⚠️ 注意:当栈为空时,pop()
方法会抛出 NoSuchElementException
。
3.2 用作队列(Queue)
现在展示如何将 ArrayDeque
当作普通队列使用,添加元素:
@Test
public void whenOffer_addsAtLast() {
Deque<String> queue = new ArrayDeque<>();
queue.offer("first");
queue.offer("second");
assertEquals("second", queue.getLast());
}
以及从队列中取出元素:
@Test
public void whenPoll_removesFirst() {
Deque<String> queue = new ArrayDeque<>();
queue.offer("first");
queue.offer("second");
assertEquals("first", queue.poll());
}
✅ 当队列为空时,poll()
方法会返回 null
而非抛出异常。
4. ArrayDeque 实现原理
底层实现上,ArrayDeque
由一个动态数组支撑,当数组填满时会自动扩容(容量翻倍)。
初始容量为 16,通过维护 头指针(head) 和 尾指针(tail) 实现双端队列功能。下面通过图解说明核心逻辑:
4.1 作为栈的实现
下图展示了 ArrayDeque
作为栈时的操作流程:
stack.push("first")
stack.push("second")
stack.pop()
关键点:
push()
操作将元素压入栈顶,并移动头指针指向新元素pop()
操作将当前头位置元素置为null
(便于 GC),然后头指针后移一位
4.2 作为队列的实现
核心机制:
offer()
操作移动尾指针poll()
操作将头位置元素置为null
(触发 GC),然后移动头指针
4.3 重要特性总结
关于 ArrayDeque
的关键注意事项:
- ❌ 非线程安全:多线程环境下需手动同步
- ❌ 拒绝 null 元素:添加 null 会抛出
NullPointerException
- ✅ 性能优势:比同步的
Stack
快得多 - ✅ 队列性能:因内存局部性更好,比
LinkedList
更快 - ⏱️ 时间复杂度:大多数操作均摊时间复杂度为 O(1)
- ⚠️ 迭代器特性:返回的
Iterator
是 fail-fast 的 - 🔄 自动扩容:当添加元素时头尾指针相遇,数组容量自动翻倍
5. 总结
本文通过代码示例和图解,详细展示了 ArrayDeque
的核心用法和实现原理。
所有示例代码可在 GitHub 项目 中获取(基于 Maven 构建,可直接导入运行)。