247. Java 集合 - 为什么要远离 Stack 类?
虽然 Stack 类在 JDK 中依然存在,使用起来也非常简单直观,比如提供了我们期望的经典三大方法:
push(element):压入元素pop():弹出栈顶元素peek():查看栈顶元素但不移除
看到这些方法,很多初学者会觉得直接使用 Stack 很顺手。那么问题来了:
🚨 为什么不推荐 在现代
Java编程中使用Stack类?
📜 Stack 背后的故事
Stack继承自Vector类。Vector是Java在Collections Framework(集合框架)诞生之前的早期集合类。Vector和Stack都是**线程安全(synchronized)**的,即所有方法都加了锁。- 然而,在单线程程序 或者无锁高性能场景 下,这种同步机制反而会带来不必要的性能开销。
🔔 总结:
Vector和Stack并没有被标记为过时(deprecated),但官方强烈不推荐继续使用。- 在需要栈功能时,推荐使用
Deque(特别是ArrayDeque)。
✅ 推荐替代方案
| 需求 | 推荐使用 |
|---|---|
| 普通单线程栈 | Deque / ArrayDeque |
| 多线程安全的栈 | BlockingQueue 的实现,如 LinkedBlockingDeque |
🔥 示例对比:使用 Deque 替代 Stack
❌ 老式写法(使用 Stack)
java
import java.util.Stack;
public class OldStackExample {
public static void main(String[] args) {
Stack<String> stack = new Stack<>();
stack.push("A");
stack.push("B");
stack.push("C");
System.out.println(stack.pop()); // C
System.out.println(stack.peek()); // B
}
}
问题:虽然简单,但 Stack 底层是同步的,影响了单线程性能,而且是过时风格。
✅ 现代写法(使用 ArrayDeque)
java
import java.util.ArrayDeque;
import java.util.Deque;
public class ModernStackExample {
public static void main(String[] args) {
Deque<String> stack = new ArrayDeque<>();
stack.push("A");
stack.push("B");
stack.push("C");
System.out.println(stack.pop()); // C
System.out.println(stack.peek()); // B
}
}
优势:
- 无锁设计,更快更轻量。
ArrayDeque专门为栈和队列操作进行了优化。- 代码同样清晰易懂。
🏗️ 进阶:需要线程安全怎么办?
如果确实需要在多线程环境下使用栈功能,可以使用 BlockingDeque 接口的实现,例如:
java
import java.util.concurrent.LinkedBlockingDeque;
import java.util.Deque;
public class ThreadSafeStackExample {
public static void main(String[] args) {
Deque<String> stack = new LinkedBlockingDeque<>();
stack.push("A");
stack.push("B");
stack.push("C");
System.out.println(stack.pop()); // C
System.out.println(stack.peek()); // B
}
}
LinkedBlockingDeque是一个线程安全的双端队列,支持高并发访问。- 适合生产者-消费者等并发场景。
🎯 小结:使用 Deque 的三大理由
| 理由 | 描述 |
|---|---|
| 🚀 性能更好 | 无锁操作,适合大部分应用场景 |
| 🔍 语义清晰 | push/pop/peek 方法一目了然 |
| 🎯 适应更多场景 | 既可以做栈(LIFO),也可以做队列(FIFO) |
👀 互动问题
问题1 :如果你发现项目中还在用 Stack 类,你会怎么做?
答案示例:评估是否可以替换成
Deque或ArrayDeque,如果涉及并发场景,再考虑BlockingDeque的实现。
问题2 :在什么情况下你依然可能使用 Vector 或 Stack?
答案示例:如果在维护极老旧的遗留系统,需要兼容性优先考虑,但新代码中应避免使用。