当前位置: 首页 > news >正文

Java中栈实现怎么选?Stack、Deque、ArrayDeque、LinkedList(含常用Api积累)

目录

Java中的Stack类

不用Stack有以下两点原因

1、从性能上来说应该使用Deque代替Stack。

2、Stack从Vector继承是个历史遗留问题,JDK官方已建议优先使用Deque的实现类来代替Stack。

该用ArrayDeque还是LinkedList?

ArrayDeque与LinkList区别:

ArrayDeque:

LinkList:

结论

API积累

Deque中常用方法:

把Deque当栈用的时候:

把Deque当队列用的时候:

从上面(头部)插入:

从上面(头部)出来/观察:

从下面(尾部)插入:

从下面(尾部)出来/观察:

Java中的Stack类

Java中Stack类从Vector类继承,底层是用数组实现的线程安全的栈。栈是一种后进先出(LIFO)的容器,常用的操作push/pop/peek

不过Java中用来表达栈的功能(push/pop/peek),更适用的是使用双端队列接口Deque,并用实现类ArrayDequeLinkedList来进行初始化。

Deque<Integer> stack = new ArrayDeque<>();
Deque<Integer> stack = new LinkedList<>();

不用Stack有以下两点原因

1、从性能上来说应该使用Deque代替Stack。

Stack和Vector都是线程安全的,其实多数情况下并不需要做到线程安全,因此没有必要使用Stack。毕竟保证线程安全需要上锁,有额外的系统开销。

2、Stack从Vector继承是个历史遗留问题,JDK官方已建议优先使用Deque的实现类来代替Stack。

Stack从Vector继承的一个副作用是,暴露了set/get方法,可以进行随机位置的访问,这与Stack只能从尾巴上进行增减的本意相悖。

此外,Deque在转成ArrayList或者stream的时候保持了“后进先出”的语义,而Stack因为是从Vector继承,没有这个语义。

Stack<Integer> stack = new Stack<>();
Deque<Integer> deque = new ArrayDeque<>();stack.push(1);
stack.push(2);
deque.push(1);
deque.push(2);System.out.println(new ArrayList<>(stack)); // [1,2]
List<Integer> list1 = stack.stream().collect(Collectors.toList());//[1,2]// deque转成ArrayList或stream时保留了“后进先出”的语义
System.out.println(new ArrayList<>(deque)); // [2,1]
List<Integer> list2 = deque.stream().collect(Collectors.toList());//[2,1]

该用ArrayDeque还是LinkedList?

ArrayDeque和LinkedList这两者底层,一个采用数组存储,一个采用链表存储;

ArrayDeque与LinkList区别:

ArrayDeque:

  • 数组结构
  • 插入元素不能为null
  • 无法确定数据量时,后期扩容会影响效率

LinkList:

  • 链表结构
  • 插入元素能为null
  • 无法确定数据量时,有更好表现

PS:这两者既可当成(仅支持在尾部加入或移除元素)使用;也可当成双端队列使用,即可以在队列的两端(头或尾)将元素加入或移除。
单次加入/移除元素的平均时间复杂度均为O(1)。

那么问题来了,在用作栈时到底用ArrayDeque好还是LinkedList好呢?

注意到ArrayDeque源码注释中有一句话:
This class is likely to be faster than {@link Stack} when used as a stack,
and faster than {@link LinkedList} when used as a queue.

ArrayDeque用作栈时比Stack快没有疑问,用作队列的时候似乎也会比LinkedList快!

笔者经过50W数据量的测试,发现两者性能基本接近,ArrayDeque平均耗时在18-24ms,LinkedList耗时平均在20-28ms。

如果数据量上升到100W的话,ArrayDeque的优势会更明显。

结论:ArrayDeque会略胜一筹,不过差别通常可以忽略

public static void main(String[] args) {int length = 500000;int max = length;// 生成一个长度为length,值从1~max的随机数组int[] data = new RandomIntArray(length,1,length,max).next();int loopCount = 10;long t1, t2;t1 = System.currentTimeMillis();for (int i = 0; i < loopCount; i++) {// testArrayDeque(data);testLinkedList(data);}t2 = System.currentTimeMillis();// 测试loopCount次取平均结果System.out.println("timeTaken: " + String.format("%.1f", (t2-t1)/(double)loopCount));
}public static void testArrayDeque(int[] data) {int length = data.length;Deque<Integer> stack = new ArrayDeque<>();for (int i = 0; i < length/2; i++) {stack.push(data[i]);stack.push(data[i+1]);stack.pop();stack.push(stack.peek()+1);}
}public static void testLinkedList(int[] data) {int length = data.length;Deque<Integer> stack = new LinkedList<>();for (int i = 0; i < length/2; i++) {stack.push(data[i]);stack.push(data[i+1]);stack.pop();stack.push(stack.peek()+1);}
}

结论

ArrayDeque会略胜一筹,不过差别通常可以忽略
经过性能对比,笔者更倾向于使用ArrayDeque来表达Java中的栈功能。


API积累

Deque中常用方法:

以这2个为基础整出来的Deque除了结构不一样,方法都一样的。

把Deque当栈用的时候:
入栈push(E e)
出栈poll() / pop() 后者在栈空的时候会抛出异常,前者返回null
查看栈顶peek() 为空时返回null
把Deque当队列用的时候:
入队offer(E e)
出队poll() 为空时返回null
查看队首peek() 为空时返回null

有些时候需要进行一些骚操作的时候(比如取得栈底元素,取得队尾元素),这些常规操作就不能满足了。
下面就是Deque中一些更详细的方法。

从上面(头部)插入:
方法名作用
void addFirst(E e)将指定的元素插入此双端队列的前面 ,空间不足抛异常
boolean offerFirst(E e)将指定的元素插入此双端队列的前面 ,空间不足插入失败返回回false
void push(E e)将指定的元素插入此双端队列的前面 ,空间不足抛异常
从上面(头部)出来/观察:
方法名作用
E removeFirst()检索并删除第一个元素,为空时抛出异常
E remove()和removeFirst一样 检索并删除第一个元素,为空时抛出异常
E pop()和removeFirst一样 检索并删除第一个元素,为空时抛出异常
E pollFirst()检索并删除第一个元素 ,为空时返回null
E poll()和pollFirst一样 检索并删除第一个元素 ,为空时返回null
E getFirst()只看看第一个元素 ,不出来,为空就抛异常
E element()和getFirst一样 只看看第一个元素 ,不出来,为空就抛异常
E peekFirst()只看看第一个元素 ,不出来,为空时返回null
E peek()和peekFirst一样 只看看第一个元素 ,不出来,为空时返回null
从下面(尾部)插入:
方法名作用
void addLast(E e)将指定的元素插入此双端队列的后面 ,空间不足抛异常
boolean offerLast(E e)将指定的元素插入此双端队列的后面,空间不足返回false
boolean add(E e)将指定的元素插入此双端队列的后面,空间不足抛异常
boolean offer(E e)将指定的元素插入此双端队列的后面,空间不足返回false
从下面(尾部)出来/观察:
方法名作用
E removeLast()检索并删除最后一个元素,为空时抛出异常
E pollLast()检索并删除最后一个元素 ,为空时返回null
E getLast()只看看最后一个元素 ,不出来,为空就抛异常
E peekLast()只看看最后一个元素 ,不出来,为空时返回null

相关文章:

Java中栈实现怎么选?Stack、Deque、ArrayDeque、LinkedList(含常用Api积累)

目录 Java中的Stack类 不用Stack有以下两点原因 1、从性能上来说应该使用Deque代替Stack。 2、Stack从Vector继承是个历史遗留问题&#xff0c;JDK官方已建议优先使用Deque的实现类来代替Stack。 该用ArrayDeque还是LinkedList&#xff1f; ArrayDeque与LinkList区别&#xff1…...

雷达分辨率单元、单向/双向雷达方程、天气雷达方程简介

一、点状目标 如果两个点状目标在一个分辨率单元中,经典脉冲雷达只能看到一个目标。 点状目标 二、雷达距离分辨率 对于简单的键控开/关脉冲调制: 对于使用脉冲内调制的雷达,距离分辨率取决于压缩脉冲的脉冲持续时间。脉冲压缩比(PCR)取决于传输带宽BWtx,即距离分辨率取…...

RabbitMQ之Fanout(扇形) Exchange解读

目录 基本介绍 适用场景 springboot代码演示 演示架构 工程概述 RabbitConfig配置类&#xff1a;创建队列及交换机并进行绑定 MessageService业务类&#xff1a;发送消息及接收消息 主启动类RabbitMq01Application&#xff1a;实现ApplicationRunner接口 基本介绍 Fa…...

Redisson—分布式集合详述

7.1. 映射&#xff08;Map&#xff09; 基于Redis的Redisson的分布式映射结构的RMap Java对象实现了java.util.concurrent.ConcurrentMap接口和java.util.Map接口。与HashMap不同的是&#xff0c;RMap保持了元素的插入顺序。该对象的最大容量受Redis限制&#xff0c;最大元素数…...

开发做前端好还是后端好?这是个问题!

前言 随着互联网的快速发展&#xff0c;越来越多的人选择从事Web开发行业&#xff0c;而Web开发涉及到前端和后端两个方面&#xff0c;相信许多人都曾经对这两个方面进行过探究。而且编程世界就像一座大城市&#xff0c;前端开发和后端开发就像城市的两个不同街区。作为初学者&…...

运行huggingface Kosmos2报错 nameerror: name ‘kosmos2tokenizer‘ is not defined

尝试运行huggingface上的Kosmos,https://huggingface.co/ydshieh/kosmos-2-patch14-224失败,报错: nameerror: name kosmos2tokenizer is not defined查看报错代码: vi /root/.cache/huggingface/modules/transformers_modules/ydshieh/kosmos-2-patch14-224/48e3edebaeb…...

吃鸡玩家必备神器!一站式提升战斗力、分享干货!

大家好&#xff0c;我是吃鸡玩家。在这个视频中&#xff0c;我要分享一个让你瞬间提高战斗力的神器&#xff0c;同时让你享受到顶级游戏作战干货的盛宴&#xff01;让我们一起来了解吧&#xff01; 首先&#xff0c;我们推荐绝地求生作图工具。通过这款工具&#xff0c;你可以轻…...

【maven】idea中基于maven-webapp骨架创建的web.xml问题

IDEA中基于maven-webapp骨架创建的web工程&#xff0c;默认的web.xml是这样的。 <!DOCTYPE web-app PUBLIC"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN""http://java.sun.com/dtd/web-app_2_3.dtd" ><web-app><display-name…...

【算法题】2034. 股票价格波动

插&#xff1a; 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 坚持不懈&#xff0c;越努力越幸运&#xff0c;大家一起学习鸭~~~ 题目&#xff1a; 给你一支股票价格的数据流。数据流…...

APSIM模型】作物模型应用案例

APSIM (Agricultural Production Systems sIMulator)模型是世界知名的作物生长模拟模型之一。APSIM模型有Classic和Next Generation两个系列模型&#xff0c;能模拟几十种农作物、牧草和树木的土壤-植物-大气过程&#xff0c;被广泛应用于精细农业、水肥管理、气候变化、粮食安…...

io_uring之liburing库安装

手动编译和安装 liburing&#xff1a; 1.首先&#xff0c;从 liburing 的 GitHub 仓库中获取源代码。您可以使用以下命令克隆仓库&#xff1a; git clone https://github.com/axboe/liburing.git2.进入 liburing 目录&#xff1a; cd liburing3.运行configure ./configure …...

Python WebSocket自动化测试:构建高效接口测试框架!

为了更高效地进行WebSocket接口的自动化测试&#xff0c;我们可以搭建一个专门的测试框架。本文将介绍如何使用Python构建一个高效的WebSocket接口测试框架&#xff0c;并重点关注以下四个方面的内容&#xff1a;运行测试文件封装、报告和日志的封装、数据驱动测试以及测试用例…...

MySQL数据库——SQL优化(1)-介绍、插入数据、主键优化

目录 介绍 插入数据 Insert 大批量插入数据 主键优化 数据组织方式 页分裂 页合并 索引设计原则 介绍 SQL优化将分为下面几个部分进行学习&#xff1a; 插入数据主键优化order by优化group by优化limit优化count优化update优化 首先就先来看第一方面&#xff0c; 插…...

Flink---10、处理函数(基本处理函数、按键分区处理函数、窗口处理函数、应用案例TopN、侧输出流)

星光下的赶路人star的个人主页 我的敌手就是我自己&#xff0c;我要他美好到能使我满意的程度 文章目录 1、处理函数1.1 基本处理函数&#xff08;ProcessFunction&#xff09;1.1.1 处理函数的功能和使用1.1.2 ProcessFunction解析1.1.3 处理函数的分类 1.2 按键分区处理函数&…...

多种方案教你彻底解决mac npm install -g后仍然不行怎么办sudo: xxx: command not found

问题概述 某些时候我们成功执行了npm install -g xxx&#xff0c;但是执行完成以后&#xff0c;使用我们全局新安装的包依然不行&#xff0c;如何解决呢&#xff1f; 解决方案1&#xff1a; step1: 查看npm 全局文件安装地址 XXXCN_CXXXMD6M ~ % npm list -g …...

斐波那契数列 JS

问题&#xff1a; 给出一个数字&#xff0c;找出它是斐波那契数列中的第几个数 斐波那契数列 [1, 1, 2, 3, 5, 8, 13, ...]&#xff0c;后一个数字是前两个数字之和 输入的数字大于等于 2 如果输入数字不存于斐波那契数列中&#xff0c;返回 -1 function demo(num) {//初始数据…...

IP 地址的分类

IP地址是用于标识计算机或设备在互联网上的位置的一种地址。IP地址通常根据其范围和用途分为不同的分类&#xff0c;主要包括以下几种&#xff1a; IPv4地址&#xff08;Internet Protocol version 4&#xff09;&#xff1a; IPv4地址是32位二进制数&#xff0c;通常以点分十…...

CDN网络基础入门:CDN原理及架构

背景 互联网业务的繁荣让各类门户网站、短视频、剧集观看、在线教育等内容生态快速发展&#xff0c;互联网流量呈现爆发式增长&#xff0c;自然也面临着海量内容分发效率上的挑战&#xff0c;那么作为终端用户&#xff0c;我们获取资源的体验是否有提升呢&#xff1f; 答案是…...

李沐深度学习记录2:10多层感知机

一.简要知识记录 x.numel()&#xff1a;看向量或矩阵里元素个数 A.sum()&#xff1a;向量或矩阵求和&#xff0c;axis参数可对某维度求和&#xff0c;keepdims参数设置是否保持维度不变 A.cumsum&#xff1a;axis参数设置沿某一维度计算矩阵累计和x*y:向量的按元素乘法 torch.…...

Python标准库中内置装饰器@staticmethod@classmethod

装饰器是Python中强大而灵活的功能&#xff0c;用于修改或增强函数或方法的行为。装饰器本质上是一个函数&#xff0c;它接受另一个函数作为参数&#xff0c;并返回一个新的函数&#xff0c;通常用于在不修改原始函数代码的情况下添加额外的功能或行为。这种技术称为元编程&…...

终极指南:Fn与云原生生态的完美集成,如何与Istio、Prometheus等工具无缝协作

终极指南&#xff1a;Fn与云原生生态的完美集成&#xff0c;如何与Istio、Prometheus等工具无缝协作 【免费下载链接】fn The container native, cloud agnostic serverless platform. 项目地址: https://gitcode.com/gh_mirrors/fn/fn Fn是一款容器原生的无服务器平台&…...

MiniCPM-o-4.5-nvidia-FlagOS与ChatGPT对比评测:代码生成与逻辑推理

MiniCPM-o-4.5-nvidia-FlagOS与ChatGPT对比评测&#xff1a;代码生成与逻辑推理 最近在开发者圈子里&#xff0c;关于开源大模型和闭源大模型谁更强的讨论一直没停过。特别是涉及到代码生成和逻辑推理这种硬核任务&#xff0c;大家心里都有一杆秤。今天&#xff0c;我们就拿一…...

PSIM仿真:基于三相桥式逆变器的下垂控制与LC滤波、SPWM调制

&#xff08;PSIM&#xff09;下垂控制-基于三相桥式逆变器的下垂控制&#xff0c;电压电流双闭环&#xff0c;采用LC滤波&#xff0c;SPWM调制方式 1.提供PSIM仿真源文件 2.提供下垂控制原理与下垂系数计算方法 3.中点平衡控制&#xff0c;电压电流双闭环控制 提供参考文献下垂…...

30分钟快速搭建企业级工作流系统:RuoYi-Flowable-Plus完整指南

30分钟快速搭建企业级工作流系统&#xff1a;RuoYi-Flowable-Plus完整指南 【免费下载链接】RuoYi-Flowable-Plus 本项目基于 RuoYi-Vue-Plus 进行二次开发扩展Flowable工作流功能&#xff0c;支持在线表单设计和丰富的工作流程设计能力。如果觉得这个项目不错&#xff0c;麻烦…...

动态规划专练:力扣第509、70、746题

由于对动态规划DP算法 掌握得不是很好&#xff0c;所以决定进行动态规划专项训练。动态规划五部曲①确定dp[i]含义②递推公式③dp数组如何初始化④遍历顺序⑤打印dp数组&#xff08;debug&#xff09;除了第五条在力扣上不开会员无法实现外&#xff0c;其余四项就是做出dp类型题…...

终极Illusion游戏Mod管理指南:用KKManager告别插件混乱

终极Illusion游戏Mod管理指南&#xff1a;用KKManager告别插件混乱 【免费下载链接】KKManager Mod, plugin and card manager for games by Illusion that use BepInEx 项目地址: https://gitcode.com/gh_mirrors/kk/KKManager 你是否曾经因为Mod冲突导致游戏崩溃而烦恼…...

单片机Shell开发避坑指南:从Putty特殊字符处理到内存安全的7个实战经验

单片机Shell开发避坑指南&#xff1a;从Putty特殊字符处理到内存安全的7个实战经验 当你在深夜调试单片机Shell时&#xff0c;突然发现退格键会导致整个系统崩溃&#xff0c;或者用户输入超长字符串后设备莫名其妙重启——这些看似简单的交互问题&#xff0c;往往成为项目交付前…...

5大突破性功能:重新定义Mac微信体验的终极指南

5大突破性功能&#xff1a;重新定义Mac微信体验的终极指南 【免费下载链接】WeChatExtension-ForMac Mac微信功能拓展/微信插件/微信小助手(A plugin for Mac WeChat) 项目地址: https://gitcode.com/gh_mirrors/we/WeChatExtension-ForMac 你是否曾因微信消息被撤回而错…...

嵌入式无锁环形缓冲区:SPSC零依赖实现

1. 项目概述nl_ring_buffer是一个极简、零依赖、可移植的环形缓冲区&#xff08;Circular Buffer&#xff09;实现&#xff0c;专为嵌入式系统底层开发设计。其核心目标并非提供功能堆砌&#xff0c;而是以最小代码体积、确定性执行时间、无动态内存分配、无锁&#xff08;lock…...

Python金融计算提速迫在眉睫!(仅剩3类未公开的底层优化手段,第3种已被高盛2023年专利覆盖)

第一章&#xff1a;Python金融计算提速迫在眉睫&#xff01;&#xff08;仅剩3类未公开的底层优化手段&#xff0c;第3种已被高盛2023年专利覆盖&#xff09;高频回测、实时风险敞口计算与蒙特卡洛期权定价正面临Python原生执行效率的严峻瓶颈。当单次万标的风险因子矩阵运算耗…...