arraydeque 是比 stack 和 linkedlist 更优的栈实现,因其循环数组结构提升缓存命中率、无锁无冗余字段、内存占用小、操作快且 null 安全;应预估容量、避免混用双端操作、复用实例以进一步优化性能。

直接用 ArrayDeque 替代 Stack 或 LinkedList 作栈,就能显著降低内存占用、提升性能。它不是“需要改造”的替代品,而是开箱即用的更优解。
为什么 ArrayDeque 天然更轻更快
ArrayDeque 底层是循环数组,元素连续存储在内存中,CPU 缓存命中率高;而 LinkedList 每个节点都是独立对象,分散在堆上,访问跳来跳去,缓存不友好。Stack 则继承自 Vector,自带 synchronized 锁和冗余字段(如 capacityIncrement),哪怕单线程也白耗资源。
- 内存方面:ArrayDeque 初始仅分配一个长度为 16 的 Object[] 数组;LinkedList 每次 push 都 new 一个含 3 字段(item/next/prev)的 Node 对象;Stack 还额外维护 capacity 和 modCount 等字段
- 操作开销:ArrayDeque 的 push/pop 是纯指针位移 + 数组索引赋值(
(head - 1) & (length - 1)),无对象创建;LinkedList 必须分配 Node 对象,触发 GC 压力;Stack 的 push 还要先加锁再复制数组 - null 安全:ArrayDeque 明确禁止 null 元素,省去了空值校验分支,也避免了因 null 导致的意外扩容或逻辑错误
正确初始化与容量预估
避免默认构造带来的多次小规模扩容。如果能预估栈深(比如解析嵌套不超过 100 层的 JSON),就显式指定初始容量:
-
new ArrayDeque<string>(128)</string>—— 容量设为 2 的幂(如 64/128/256),位运算索引更高效 - 扩容是翻倍策略(
n ),均摊 O(1);但若频繁扩容,仍会触发数组复制和 GC,所以合理预估很关键 - 不要用
new ArrayDeque()后立刻ensureCapacity——ArrayDeque 没有该方法,扩容完全由内部自动触发
栈操作写法与常见误区
API 与 Stack 高度兼容,但语义更清晰:
- 压栈用
push(E)(等价于addFirst(E)),弹栈用pop()(等价于removeFirst()),查栈顶用peek() - 避免混用双端操作:比如一边
push()一边addLast(),会破坏 LIFO 逻辑,也影响 head/tail 指针预期行为 - 不要调用
size()判断是否为空——用isEmpty()更直接,且部分场景下 size 计算可能隐含遍历开销(虽然 ArrayDeque 是 O(1),但习惯上应统一)
实战中进一步减负的小技巧
在高频短生命周期栈场景(如递归模拟、表达式求值、DFS 路径暂存),可配合以下做法:
- 复用栈实例:避免每次新建,改为方法参数传入或线程局部变量(
ThreadLocal<arraydeque>></arraydeque>),减少对象分配 - 及时清理引用:pop 后原元素引用不会自动置 null,若栈中存的是大对象,且栈生命周期长,可手动
elements[head] = null(需反射或子类封装,一般无需) - 不用
toArray()导出全量——若只是临时遍历,用增强 for 循环或迭代器即可,避免额外数组拷贝











