跳转到主内容
极星编程网:以代码为星,赴技术山海!

如何在 Java 中使用 Stack 类实现后进先出的栈结构

不该用 Stack 类,因其继承过时的 Vector、同步开销大、破坏封装(如 get(i) 可随意访问中间元素);应改用 ArrayDeque 实现 Deque 接口,性能更好、API 更纯粹。 Java 的
Stack
类不推荐用于新代码,它继承自过时的
Vector
,线程安全但性能差,且设计违反封装原则(比如能用
get(i)
随意访问中间元素)。 为什么不该用
Stack
类 它本质是带额外方法的
Vector
,所有操作都加了
synchronized
,即使单线程也白耗开销;
push()
和
pop()
底层调用的是
addElement()
和
removeElementAt(size()-1)
,语义冗余;更严重的是,它公开了
elementAt()
、
setSize()
等破坏栈抽象的方法。 实际项目中,JDK 官方文档明确建议用
Deque
实现栈,比如
ArrayDeque
—— 它更快、更轻量、API 更纯粹。 用
ArrayDeque
替代
Stack
的正确写法 把
Stack stack = new Stack<>();
换成: 立即学习 “ Java免费学习笔记(深入) ”;
Deque stack = new ArrayDeque<>();
对应操作直接映射:
stack.push("a")
→ 仍可用(
ArrayDeque
实现了
push()
)
stack.pop()
→ 返回栈顶并移除,行为一致
stack.peek()
→ 查看栈顶不移除,和
Stack
一样
stack.isEmpty()
→ 判空,无差异 注意:
ArrayDeque
不支持
null
元素,而
Stack
可以——如果业务逻辑真依赖存
null
,说明栈设计本身就有问题,该重构。 Eclipse导入Android或其他的JAVA项目的正确方法 WORD版 本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看 下载 遇到
EmptyStackException
怎么办 无论是
Stack.pop()
还是
ArrayDeque.pop()
,在空时都会抛
EmptyStackException
。这不是 bug,是契约行为。 安全做法永远是先判空再操作:
if (!stack.isEmpty()) { String top = stack.pop(); }
别依赖
try-catch
来控制流程——这会掩盖真实异常,且性能差。有些旧代码用
stack.size() > 0
判断,对
ArrayDeque
没问题,但
size()
对某些
Deque
实现(如并发场景下的
ConcurrentLinkedDeque
)可能不精确,所以坚持用
isEmpty()
。 如果必须兼容老
Stack
接口怎么办 比如对接遗留系统或第三方库强制要求
Stack
类型参数。这时不要继承
Stack
或包装它,而是用适配器模式最小化侵入:
public class DequeStack extends Stack { private final Deque delegate = new ArrayDeque<>(); @Override public E push(E item) { delegate.push(item); return item; } @Override public synchronized E pop() { if (delegate.isEmpty()) throw new EmptyStackException(); return delegate.pop(); } // 其他方法同理,只转发到 delegate,屏蔽 Vector 特性 }
关键点: 重写所有方法,确保内部只走
ArrayDeque
保留
synchronized
仅为了满足
Stack
接口签名,实际已无同步必要 绝不在外部暴露
delegate
或调用
super
的
Vector
方法 真正难的不是语法,是意识到:栈不是“能后进先出就行”,而是“接口干净、行为可预测、扩展无隐患”。用错容器,后面 debug 时看到
Stack.size()
返回 5 但
peek()
却抛异常,就只能翻源码了。

相关文章