Java中栈的多种实现类详解
Java中栈的多种实现类详解:Stack、LinkedList与ArrayDeque全方位对比
- 前言
- 一、Stack类——Java最早的栈实现
- 1.1 Stack类简介
- 1.2 常用方法
- 1.3 优缺点分析
- 二、LinkedList类——灵活的双端链表
- 2.1 LinkedList类简介
- 2.2 常用方法
- 2.3 优缺点分析
- 三、ArrayDeque类——高性能的现代选择
- 3.1 ArrayDeque类简介
- 3.2 常用方法
- 3.3 优缺点分析
- 四、三者方法对比
- 五、代码实现
- 5.1 Stack实现
- 5.2 LinkedList实现
- 5.3 ArrayDeque实现
- 六、线程安全与高并发场景下的栈实现
- 6.1 Stack的线程安全
- 6.2 ArrayDeque/LinkedList的线程安全处理
- 6.3 高并发场景下的栈实现
- 七、总结与最佳实践
- 参考资料
前言
在日常开发和算法题中,栈(Stack)是一种非常常用的数据结构,它遵循“后进先出(LIFO)”的原则,常用于括号匹配、表达式求值、递归模拟等场景。那么在Java中,我们该如何选择合适的栈实现类?本文我将详细分析Java中三种常见的栈实现方式:Stack
、LinkedList
、ArrayDeque
,并通过原理对比它们的优缺点,最后探讨在多线程/高并发场景下的栈实现方案。
一、Stack类——Java最早的栈实现
1.1 Stack类简介
Stack
类是Java 1.0就引入的栈实现,位于java.util
包下。它继承自Vector
,本质上是一个线程安全的动态数组。
1.2 常用方法
Stack<Integer> stack = new Stack<>();
stack.push(1); // 入栈
stack.push(2);
int top = stack.pop(); // 出栈,返回2
int peek = stack.peek(); // 查看栈顶元素,不移除
boolean empty = stack.empty(); // 判断栈是否为空
int pos = stack.search(1); // 查找元素,返回距离栈顶的偏移量
1.3 优缺点分析
优点:
- 直接实现了栈的常用操作,API简单易用。
- 线程安全,所有方法都加了
synchronized
。
缺点:
- 继承自
Vector
,设计上有历史包袱,方法和结构不够现代化。 - 线程安全带来的同步开销,单线程下性能较差。
- Java官方已不推荐新代码使用,属于遗留类(legacy class)。
二、LinkedList类——灵活的双端链表
2.1 LinkedList类简介
LinkedList
实现了Deque
接口,可以作为栈、队列、双端队列使用。底层是双向链表结构。
2.2 常用方法
LinkedList<Integer> stack = new LinkedList<>();
stack.push(1); // 入栈
stack.push(2);
int top = stack.pop(); // 出栈,返回2
int peek = stack.peek(); // 查看栈顶元素,不移除
boolean empty = stack.isEmpty(); // 判断栈是否为空
注意:
LinkedList
的push
/pop
/peek
方法其实是Deque
接口的方法,等价于addFirst
/removeFirst
/getFirst
。
2.3 优缺点分析
优点:
- 实现了
Deque
接口,方法丰富,既能做栈也能做队列。 - 插入和删除操作效率高(O(1)),适合频繁增删。
- 灵活性高,支持双端操作。
缺点:
- 不是线程安全的。
- 每个节点有额外的指针开销,内存占用比数组大。
- 访问元素时需要遍历链表,随机访问性能差。
三、ArrayDeque类——高性能的现代选择
3.1 ArrayDeque类简介
ArrayDeque
同样实现了Deque
接口,底层用循环数组实现。它是Java官方推荐的栈/队列实现。
3.2 常用方法
ArrayDeque<Integer> stack = new ArrayDeque<>();
stack.push(1); // 入栈
stack.push(2);
int top = stack.pop(); // 出栈,返回2
int peek = stack.peek(); // 查看栈顶元素,不移除
boolean empty = stack.isEmpty(); // 判断栈是否为空
注意:
ArrayDeque
不能存储null
元素,否则会抛出NullPointerException
。
3.3 优缺点分析
优点:
- 实现了
Deque
接口,方法丰富,既能做栈也能做队列。 - 基于数组,内存利用率高,局部性好,性能优于
LinkedList
。 - 没有同步开销,单线程下性能最好。
- 支持栈和队列操作,灵活性高。
缺点:
- 不是线程安全的。
- 数组需要扩容时有一定的性能开销。
- 不能存储
null
元素。
四、三者方法对比
方法/类 | Stack | LinkedList | ArrayDeque |
---|---|---|---|
push(E e) | 有 | 有 | 有 |
pop() | 有 | 有 | 有 |
peek() | 有 | 有 | 有 |
empty()/isEmpty() | 有 | 有 | 有 |
search(Object o) | 有 | 无 | 无 |
线程安全 | 是 | 否 | 否 |
支持null元素 | 是 | 是 | 否 |
随机访问 | 支持 | 不支持 | 不支持 |
性能 | 较低 | 一般 | 最优 |
五、代码实现
5.1 Stack实现
Stack<Integer> stack = new Stack<>();
stack.push(10);
stack.push(20);
System.out.println(stack.pop()); // 20
System.out.println(stack.peek()); // 10
System.out.println(stack.empty()); // false
5.2 LinkedList实现
LinkedList<Integer> stack = new LinkedList<>();
stack.push(10);
stack.push(20);
System.out.println(stack.pop()); // 20
System.out.println(stack.peek()); // 10
System.out.println(stack.isEmpty()); // false
5.3 ArrayDeque实现
ArrayDeque<Integer> stack = new ArrayDeque<>();
stack.push(10);
stack.push(20);
System.out.println(stack.pop()); // 20
System.out.println(stack.peek()); // 10
System.out.println(stack.isEmpty()); // false
六、线程安全与高并发场景下的栈实现
6.1 Stack的线程安全
Stack
类的所有方法都加了synchronized
,天然线程安全。但由于同步粒度较粗,性能较低,不适合高并发场景。
6.2 ArrayDeque/LinkedList的线程安全处理
这两者本身不是线程安全的,如果在多线程环境下使用,可以通过Collections.synchronizedDeque
进行包装:
Deque<Integer> safeStack = Collections.synchronizedDeque(new ArrayDeque<>());
safeStack.push(1);
safeStack.push(2);
System.out.println(safeStack.pop());
6.3 高并发场景下的栈实现
如果你需要在高并发场景下使用栈,推荐使用并发包下的实现:
ConcurrentLinkedDeque
:高并发下的无界线程安全双端队列,可以作为栈使用。
Deque<Integer> concurrentStack = new ConcurrentLinkedDeque<>();
concurrentStack.push(1);
concurrentStack.push(2);
System.out.println(concurrentStack.pop());
BlockingDeque
:支持阻塞操作的双端队列,适合生产者-消费者场景。
BlockingDeque<Integer> blockingStack = new LinkedBlockingDeque<>();
blockingStack.push(1);
blockingStack.push(2);
System.out.println(blockingStack.pop());
七、总结与最佳实践
- 单线程场景:优先推荐
ArrayDeque
,性能最好,API丰富。 - 需要线程安全:用
Collections.synchronizedDeque(new ArrayDeque<>())
或ConcurrentLinkedDeque
。 - 老代码维护:
Stack
可以用,但不推荐新项目使用。 - 特殊需求:如需要阻塞、限界等功能,选择
BlockingDeque
相关实现。
参考资料
- Java官方文档 - Stack
- Java官方文档 - ArrayDeque
- Java官方文档 - LinkedList
若这篇内容帮到你,动动手指支持下!关注不迷路,干货持续输出!
ヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノ
相关文章:
Java中栈的多种实现类详解
Java中栈的多种实现类详解:Stack、LinkedList与ArrayDeque全方位对比 前言一、Stack类——Java最早的栈实现1.1 Stack类简介1.2 常用方法1.3 优缺点分析 二、LinkedList类——灵活的双端链表2.1 LinkedList类简介2.2 常用方法2.3 优缺点分析 三、ArrayDeque类——高…...
6.计算机网络核心知识点精要手册
计算机网络核心知识点精要手册 1.协议基础篇 网络协议三要素 语法:数据与控制信息的结构或格式,如同语言中的语法规则语义:控制信息的具体含义和响应方式,规定通信双方"说什么"同步:事件执行的顺序与时序…...
基于Uniapp的HarmonyOS 5.0体育应用开发攻略
一、技术架构设计 1.混合开发框架选型 (1)使用Uniapp 3.8版本支持ArkTS编译 (2)通过uni-harmony插件调用原生能力 (3)分层架构设计: graph TDA[UI层] -->|Vue语法| B(Uniapp框架)B --&g…...

【笔记】AI Agent 项目 SUNA 部署 之 Docker 构建记录
#工作记录 构建过程记录 Microsoft Windows [Version 10.0.27871.1000] (c) Microsoft Corporation. All rights reserved.(suna-py3.12) F:\PythonProjects\suna>python setup.py --admin███████╗██╗ ██╗███╗ ██╗ █████╗ ██╔════╝…...

五、jmeter脚本参数化
目录 1、脚本参数化 1.1 用户定义的变量 1.1.1 添加及引用方式 1.1.2 测试得出用户定义变量的特点 1.2 用户参数 1.2.1 概念 1.2.2 位置不同效果不同 1.2.3、用户参数的勾选框 - 每次迭代更新一次 总结用户定义的变量、用户参数 1.3 csv数据文件参数化 1、脚本参数化 …...

python基础语法Ⅰ
python基础语法Ⅰ 常量和表达式变量是什么变量的语法1.定义变量使用变量 变量的类型1.整数2.浮点数(小数)3.字符串4.布尔5.其他 动态类型特征注释注释是什么注释的语法1.行注释2.文档字符串 注释的规范 常量和表达式 我们可以把python当作一个计算器,来进行一些算术…...

C++11 constexpr和字面类型:从入门到精通
文章目录 引言一、constexpr的基本概念与使用1.1 constexpr的定义与作用1.2 constexpr变量1.3 constexpr函数1.4 constexpr在类构造函数中的应用1.5 constexpr的优势 二、字面类型的基本概念与使用2.1 字面类型的定义与作用2.2 字面类型的应用场景2.2.1 常量定义2.2.2 模板参数…...

EEG-fNIRS联合成像在跨频率耦合研究中的创新应用
摘要 神经影像技术对医学科学产生了深远的影响,推动了许多神经系统疾病研究的进展并改善了其诊断方法。在此背景下,基于神经血管耦合现象的多模态神经影像方法,通过融合各自优势来提供有关大脑皮层神经活动的互补信息。在这里,本研…...
python打卡day49@浙大疏锦行
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 一、通道注意力模块复习 & CBAM实现 import torch import torch.nn as nnclass CBAM(nn.Module):def __init__…...
Qt Quick Controls模块功能及架构
Qt Quick Controls是Qt Quick的一个附加模块,提供了一套用于构建完整用户界面的UI控件。在Qt 6.0中,这个模块经历了重大重构和改进。 一、主要功能和特点 1. 架构重构 完全重写了底层架构,与Qt Quick更紧密集成 移除了对Qt Widgets的依赖&…...
手动给中文分词和 直接用神经网络RNN做有什么区别
手动分词和基于神经网络(如 RNN)的自动分词在原理、实现方式和效果上有显著差异,以下是核心对比: 1. 实现原理对比 对比维度手动分词(规则 / 词典驱动)神经网络 RNN 分词(数据驱动)…...

C++中vector类型的介绍和使用
文章目录 一、vector 类型的简介1.1 基本介绍1.2 常见用法示例1.3 常见成员函数简表 二、vector 数据的插入2.1 push_back() —— 在尾部插入一个元素2.2 emplace_back() —— 在尾部“就地”构造对象2.3 insert() —— 在任意位置插入一个或多个元素2.4 emplace() —— 在任意…...
计算机系统结构复习-名词解释2
1.定向:在某条指令产生计算结果之前,其他指令并不真正立即需要该计算结果,如果能够将该计算结果从其产生的地方直接送到其他指令中需要它的地方,那么就可以避免停顿。 2.多级存储层次:由若干个采用不同实现技术的存储…...
HTML中各种标签的作用
一、HTML文件主要标签结构及说明 1. <!DOCTYPE html> 作用:声明文档类型,告知浏览器这是 HTML5 文档。 必须:是。 2. <html lang“zh”>. </html> 作用:包裹整个网页内容,lang"z…...

CVE-2023-25194源码分析与漏洞复现(Kafka JNDI注入)
漏洞概述 漏洞名称:Apache Kafka Connect JNDI注入导致的远程代码执行漏洞 CVE编号:CVE-2023-25194 CVSS评分:8.8 影响版本:Apache Kafka 2.3.0 - 3.3.2 修复版本:≥ 3.4.0 漏洞类型:反序列化导致的远程代…...
统计学(第8版)——统计抽样学习笔记(考试用)
一、统计抽样的核心内容与问题 研究内容 从总体中科学抽取样本的方法利用样本数据推断总体特征(均值、比率、总量)控制抽样误差与非抽样误差 解决的核心问题 在成本约束下,用少量样本准确推断总体特征量化估计结果的可靠性(置…...

Copilot for Xcode (iOS的 AI辅助编程)
Copilot for Xcode 简介Copilot下载与安装 体验环境要求下载最新的安装包安装登录系统权限设置 AI辅助编程生成注释代码补全简单需求代码生成辅助编程行间代码生成注释联想 代码生成 总结 简介 尝试使用了Copilot,它能根据上下文补全代码,快速生成常用…...

Axure零基础跟我学:展开与收回
亲爱的小伙伴,如有帮助请订阅专栏!跟着老师每课一练,系统学习Axure交互设计课程! Axure产品经理精品视频课https://edu.csdn.net/course/detail/40420 课程主题:Axure菜单展开与收回 课程视频:...
Docker、Wsl 打包迁移环境
电脑需要开启wsl2 可以使用wsl -v 查看当前的版本 wsl -v WSL 版本: 2.2.4.0 内核版本: 5.15.153.1-2 WSLg 版本: 1.0.61 MSRDC 版本: 1.2.5326 Direct3D 版本: 1.611.1-81528511 DXCore 版本: 10.0.2609…...

RabbitMQ 各类交换机
为什么要用交换机? 交换机用来路由消息。如果直发队列,这个消息就被处理消失了,那别的队列也需要这个消息怎么办?那就要用到交换机 交换机类型 1,fanout:广播 特点 广播所有消息:将消息…...

高保真组件库:开关
一:制作关状态 拖入一个矩形作为关闭的底色:44 x 22,填充灰色CCCCCC,圆角23,边框宽度0,文本为”关“,右对齐,边距2,2,6,2,文本颜色白色FFFFFF。 拖拽一个椭圆,尺寸18 x 18,边框为0。3. 全选转为动态面板状态1命名为”关“。 二:制作开状态 复制关状态并命名为”开…...

未授权访问事件频发,我们应当如何应对?
在当下,数据已成为企业和组织的核心资产,是推动业务发展、决策制定以及创新的关键驱动力。然而,未授权访问这一隐匿的安全威胁,正如同高悬的达摩克利斯之剑,时刻威胁着数据的安全,一旦触发,便可…...
Easy Excel
Easy Excel 一、依赖引入二、基本使用1. 定义实体类(导入/导出共用)2. 写 Excel3. 读 Excel 三、常用注解说明(完整列表)四、进阶:自定义转换器(Converter) 其它自定义转换器没生效 Easy Excel在…...

欢乐熊大话蓝牙知识17:多连接 BLE 怎么设计服务不会乱?分层思维来救场!
多连接 BLE 怎么设计服务不会乱?分层思维来救场! 作者按: 你是不是也遇到过 BLE 多连接时,调试现场像网吧“掉线风暴”? 温度传感器连上了,心率带丢了;一边 OTA 更新,一边通知卡壳。…...
AWS vs 阿里云:功能、服务与性能对比指南
在云计算领域,Amazon Web Services (AWS) 和阿里云 (Alibaba Cloud) 是全球领先的提供商,各自在功能范围、服务生态系统、性能表现和适用场景上具有独特优势。基于提供的引用[1]-[5],我将从功能、服务和性能三个方面进行结构化对比分析&#…...
用js实现常见排序算法
以下是几种常见排序算法的 JS实现,包括选择排序、冒泡排序、插入排序、快速排序和归并排序,以及每种算法的特点和复杂度分析 1. 选择排序(Selection Sort) 核心思想:每次从未排序部分选择最小元素,与未排…...
python读取SQLite表个并生成pdf文件
代码用于创建含50列的SQLite数据库并插入500行随机浮点数据,随后读取数据,通过ReportLab生成横向PDF表格,包含格式化(两位小数)及表头、网格线等美观样式。 # 导入所需库 import sqlite3 # 用于操作…...
当下AI智能硬件方案浅谈
背景: 现在大模型出来以后,打破了常规的机械式的对话,人机对话变得更聪明一点。 对话用到的技术主要是实时音视频,简称为RTC。下游硬件厂商一般都不会去自己开发音视频技术,开发自己的大模型。商用方案多见为字节、百…...
大模型真的像人一样“思考”和“理解”吗?
Yann LeCun 新研究的核心探讨:大语言模型(LLM)的“理解”和“思考”方式与人类认知的根本差异。 核心问题:大模型真的像人一样“思考”和“理解”吗? 人类的思考方式: 你的大脑是个超级整理师。面对海量信…...
【题解-洛谷】P10480 可达性统计
题目:P10480 可达性统计 题目描述 给定一张 N N N 个点 M M M 条边的有向无环图,分别统计从每个点出发能够到达的点的数量。 输入格式 第一行两个整数 N , M N,M N,M,接下来 M M M 行每行两个整数 x , y x,y x,y,表示从 …...