247. Java 集合 - 为什么要远离 Stack 类?

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?

答案示例:如果在维护极老旧的遗留系统,需要兼容性优先考虑,但新代码中应避免使用。

相关推荐
大白8015 分钟前
CSS 盒模型精讲:标准盒模型与 IE 怪异盒模型区别
后端
深蓝AI15 分钟前
Python 写 JSON 写到一半崩了?用 os.replace 保住上一版配置(附故障注入)
后端
十年Java程序媛17 分钟前
String / StringBuilder / StringBuffer|别再乱用字符串拼接,底层原理一次讲透
java·spring boot·后端
大勇前进24 分钟前
CSS 选择器优先级详解,一次搞懂权重计算规则
后端
骑着蜗牛撵大象32727 分钟前
豆包 Seed 驱动的记账智能体:从拍票抽取到月报生成的全链路落地记录
java·前端·javascript·结构化输出·豆包seed·多模态识别·记账系统
溪语流沙29 分钟前
【Web全栈进阶】前端世界观:现代工具链与框架为什么存在
前端·javascript·vue.js
姜鱼问生36 分钟前
fail2ban 实战:从默认配置到生产可用
后端·算法·架构
kyriewen1 小时前
我逐个测了 JSON.stringify 的 7 个坑:第 1 个就在丢数据
前端·javascript·程序员
积流成海1 小时前
用代码实现哈希计算器:Web Crypto API 实战
前端·算法·哈希算法·哈希函数·盘子工具站
data analyse 4561 小时前
服务端访问日志聚合 PV 与 UV 怎么实现?日志采集与口径设计
大数据·前端·数据分析