ArrayDeque能同时高效实现栈和队列,因其基于循环数组、维护head/tail双指针,支持O(1)均摊操作;作为栈用push/pop/peek(尾端单端操作),作为队列用offer/poll/peek(头出尾进),且比Stack(同步冗余)和LinkedList(缓存不友好、GC压力大)更契合现代硬件特性。

ArrayDeque 是 Java 中一个基于循环数组实现的双端队列,既能高效模拟栈(LIFO),也能高效模拟队列(FIFO),性能优于传统 Stack 和 LinkedList。它不支持 null 元素,非线程安全,但胜在内存连续、操作均摊 O(1)、无同步开销。
为什么 ArrayDeque 能同时胜任栈和队列
核心在于其循环数组结构 + 两端独立指针(head 和 tail)的设计:
- 所有元素物理连续存储在 Object[] 数组中,CPU 缓存预取效率高,局部性好
- 只维护两个整型索引:head 指向队首元素,tail 指向队尾元素的下一个位置
- 插入/删除仅更新对应指针,不移动其他元素;越界时才扩容(容量翻倍),复制成本均摊到多次操作
- 既可单端操作(如只用 tail 端实现栈),也可双端配合(如 tail 入、head 出实现队列)
作为栈使用:统一操作尾端
推荐用 push/pop/peek 方法,语义清晰且与 Stack 类一致:
- push(e) → 等价于 addLast(e),在 tail 处插入,tail 自增
- pop() → 等价于 removeLast(),检查非空后 tail 减一并返回原 tail-1 位置元素
- peek() → 等价于 peekLast(),仅读取 tail-1 位置元素,不修改 tail
- 全程不涉及 head,也不触发 head 移动或数组搬移
作为队列使用:头出尾进标准模式
遵循 FIFO 原则,用 offer/poll/peek 配合头尾分工:
- offer(e) → 等价于 addLast(e),在 tail 插入,tail 自增
- poll() → 等价于 removeFirst(),检查非空后读取 head 位置元素,并 head 自增
- peek() → 等价于 peekFirst(),仅读取 head 位置元素,不修改 head
- head 和 tail 可“绕圈”前进(通过位运算或取模实现循环),避免假溢出
相比 Stack 和 LinkedList 的关键优势
不只是“更快”,而是底层机制更契合现代硬件特性:
- 比 Stack 快:Stack 继承 Vector,带 synchronized 开销;扩容时复制全部元素,无循环复用机制
- 比 LinkedList 快:LinkedList 每个节点分散堆内存,缓存命中率低;每次增删需新建/丢弃对象,GC 压力大
- 缓存友好:ArrayDeque 元素紧邻存储,遍历、压栈、出队都能充分利用 CPU cache line
- 空间紧凑:无额外节点引用字段,只有数组+两个 int 索引,内存占用更低











