ArrayDeque 比 Stack 和 LinkedList 更省内存,因其底层为循环数组,无节点对象开销;Stack 同步锁冗余且扩容低效,LinkedList 每元素额外占两个引用,内存浪费显著。

ArrayDeque 为什么比 Stack 和 LinkedList 更省内存
因为 ArrayDeque 底层是循环数组,没有节点对象开销;而 Stack(继承自 Vector)每个操作都带同步锁且扩容冗余大,LinkedList 每个元素额外携带两个引用(next 和 prev),光一个 Integer 元素在 64 位 JVM 上就可能占用 32 字节以上(对象头 + 引用 + 对齐填充),ArrayDeque 则接近紧凑存储。
直接用 ArrayDeque 当栈的正确姿势
ArrayDeque 本身没叫 push/pop 的方法名,但语义完全等价——别调用 addFirst/removeFirst,它们语义是双端队列操作,容易混淆;应统一用 push、pop、peek 这三个栈专用方法:
-
push(E)等价于addFirst(E),但更清晰表达栈意图 -
pop()抛出NoSuchElementException而非返回null,和传统栈行为一致 -
peek()不移除元素,安全查看栈顶,空时返回null
示例:
ArrayDeque<String> stack = new ArrayDeque<>();
stack.push("a");
stack.push("b");
String top = stack.peek(); // "b"
String popped = stack.pop(); // "b"
初始化容量要预估,否则反而浪费内存
ArrayDeque 默认构造容量是 16,但每次扩容是「翻倍」(如 16 → 32 → 64),且只支持扩容不支持缩容。如果实际栈深长期稳定在 100 左右,却用默认构造,可能经历多次扩容+数组复制,还残留大量未用槽位。
- 用
new ArrayDeque<>(initialCapacity)预设合理值,比如预估最大深度为 N,取大于等于 N 的最小 2 的幂(如 N=120 → 设 128) - 避免传 0 或负数,会触发内部兜底逻辑,实际仍建 16 容量数组
- 不要为了“省一点”设过小值,频繁扩容的 CPU 开销 + 内存碎片比多占几个引用更伤性能
注意 null 元素限制和线程不安全
ArrayDeque 明确禁止 null 入栈:push(null) 会立即抛 NullPointerException。这点和 LinkedList(允许 null)不同,也和某些手写栈实现不同——如果你业务逻辑中栈元素可能为 null,必须提前转换(如用 Optional.empty() 代替)或换结构。
它也不做任何同步,多线程共用同一个 ArrayDeque 实例当栈时,push/pop 交叉执行会导致数据错乱或 ArrayIndexOutOfBoundsException。需要线程安全?要么加外部锁,要么用 Collections.synchronizedDeque 包一层(但会损失性能优势)。
真正省内存的前提是:你清楚自己不需要 null 支持,也控制得了并发访问——这两点漏掉任何一个,ArrayDeque 的内存优势都会被掩盖。

















