
ArrayDeque 就是 Stack 的现代替代品,别再用 Stack 了
Java 官方从 JDK 1.6 起就明确不推荐 Stack,JDK 9+ 的文档里直接写“A more complete and consistent set of LIFO stack operations is provided by the Deque interface”——意思是:要栈操作,就用 Deque,别碰 Stack。这不是建议,是淘汰声明。
为什么 ArrayDeque 压倒性胜出:三个硬伤 Stack 根本改不了
Stack 的问题不是“不够好”,而是设计上就卡死在 1995 年:
-
Stack继承自Vector,所以它能调用add(2, x)、remove(0)、set(3, y)—— 这些操作让栈不再是栈,LIFO 语义彻底失效 - 所有方法都带
synchronized,单线程下也强制锁,实测压入 10 万元素,ArrayDeque吞吐量通常是Stack的 4 倍左右 - 底层用普通数组扩容(复制整个数组),初始容量 10,而
ArrayDeque用循环数组 + 位运算索引((i + 1) & (length - 1)),扩容翻倍且无取模开销
怎么把旧 Stack 代码安全换成 ArrayDeque?关键三步
替换不是简单改类型,要注意行为差异和空值处理:
- 把
Stack<string> s = new Stack();</string>换成Deque<string> s = new ArrayDeque();</string>—— 推荐用接口声明,保留灵活性 -
s.push(x)和s.pop()可直接保留;但s.peek()在空时抛NoSuchElementException,若需 null 安全,改用s.peekFirst() -
Stack允许null,ArrayDeque明确禁止null元素,插入前必须判空,否则抛NullPointerException
ArrayDeque 不是万能的:两个真实限制你得知道
它快、干净、灵活,但不是银弹:
立即学习“Java免费学习笔记(深入)”;
- 它不是线程安全的 —— 这反而是优点:多数业务栈根本不需要同步,强行加锁反而掩盖并发意图;真需要线程安全,用
Collections.synchronizedDeque(new ArrayDeque()),比Stack更可控 - 它不支持随机访问 —— 没有
get(int index),也没search(Object)这种遗留方法;如果你真需要查某个元素位置,说明你用错了数据结构,该换ArrayList或加索引缓存
真正容易被忽略的,是 null 禁止和线程安全责任上移——这两点不提前踩坑,上线后可能只在高并发或边界数据下才暴露。










