性能篇:深入源码解析和性能测试arraylist和LinkedList差异!

嗨,大家好,我是小米!今天我们要谈论的是 Java 中两个常用的集合类:ArrayList 和 LinkedList。大家都知道,这两者在新增和删除元素的操作上有一些差异,那么它们究竟在性能上有何表现呢?我们通过深入源码解析和性能测试来一探究竟!

ArrayList 新增元素到末尾

这是最常见的新增元素操作,我们使用 add 方法将元素直接添加到 ArrayList 的末尾。

源码解析

下面是 ArrayList 新增元素的关键源码:

ArrayList 新增元素到指定索引位置

有时候,我们需要在 ArrayList 的任意位置添加元素。我们可以使用 add(int index, E element) 方法,将元素插入到指定的索引位置。

源码解析

下面是在任意位置添加元素的新增操作源码:

相同之处

  • 在两种情况下,都会调用 ensureCapacityInternal 方法来确保容量足够。
  • 都会涉及数组的复制或移动操作,确保新增元素后数组的有序性。

不同之处

  • 直接加到末尾的操作无需涉及元素的移动,只需在数组末尾添加即可,效率相对较高。
  • 在任意位置添加元素的操作需要涉及数组中间元素的移动,因此效率相对较低。

LinkedList 新增元素到末尾

LinkedList 是基于双向链表实现的集合类。当我们往 LinkedList 中新增元素时,它会在链表中找到合适的位置,然后进行节点的插入操作。

源码解析

下面是 LinkedList 新增元素的核心源码:

LinkedList 新增元素到任意位置

LinkedList 通过 add(int index, E element) 方法,同样可以在任意位置添加元素。

源码解析

下面是在任意位置添加元素的新增操作源码:

相同之处

  • 直接加到末尾的操作和 ArrayList 类似,都是在末尾插入新元素。
  • 在任意位置添加元素时,也需要检查索引是否越界。

不同之处

  • 直接加到末尾的操作时,LinkedList 通过 linkLast 方法在链表末尾插入新节点。
  • 在任意位置添加元素的操作时,LinkedList 通过 linkBefore 方法在指定位置之前插入新节点,涉及更多指针的调整。

新增元素操作 JMH 测试

具体的 JMH 测试代码

测试结论

通过ArrayList 和 LinkedList 新增元素操作测试,我们可以得到:

  • 如果是从集合的头部新增元素,ArrayList 花费的时间应该比 LinkedList 多,因为需要对头部以后的元素进行复制。
  • 如果是从集合的中间位置新增元素,ArrayList 花费的时间搞不好要比 LinkedList 少,因为 LinkedList 需要遍历。
  • 如果是从集合的尾部新增元素,ArrayList 花费的时间应该比 LinkedList 少,因为数组是一段连续的内存空间,也不需要复制数组;而链表需要创建新的对象,前后引用也要重新排列。

ArrayList 删除元素

ArrayList 删除元素时,首先要找到要删除的元素位置。然后,它需要将该位置之后的所有元素向前移动一个位置,以保持数组的有序性。这个过程可能会导致性能开销,特别是在删除靠前的元素时,需要移动的元素越多,开销就越大,性能就越慢。

源码解析

下面是 ArrayList 删除元素的核心源码:

删除元素的性能开销

在 ArrayList 中删除元素的性能受到删除位置的影响。当删除靠前的元素时,需要将该位置之后的元素都向前移动,开销较大。这是因为 System.arraycopy 方法需要复制一定数量的元素,而这个数量取决于删除位置之后的元素个数。

LinkedList 删除元素

如何删除元素

LinkedList 删除元素时,首先需要找到要删除的元素位置。这里有一个特殊之处:如果要删除的元素位于链表的前半部分,LinkedList 会从链表头部开始循环查找;而如果位于后半部分,就从链表尾部开始循环查找。这是为了最大程度地减小查找的开销。

源码解析

下面是 LinkedList 删除元素的核心源码片段:

删除元素的性能特点

LinkedList 删除元素的性能特点主要取决于删除的位置。如果删除的元素靠近链表的头部或尾部,性能相对较高,因为只需在相对较短的部分内查找。然而,如果删除的元素位于链表中间,就需要从头部或尾部遍历到目标位置,性能开销相对较大。

删除元素操作 JMH 测试

具体的 JMH 测试代码

测试结论

通过 ArrayList 和 LinkedList 删除元素操作测试,我们可以得到:

  • 从集合头部删除元素时,ArrayList 花费的时间比 LinkedList 多很多;
  • 从集合中间位置删除元素时,ArrayList 花费的时间比 LinkedList 少很多;
  • 从集合尾部删除元素时,ArrayList 花费的时间比 LinkedList 少一点。

总结

由于 ArrayList 是数组实现的,而数组是一块连续的内存空间,在添加(或删除)元素到数组头部的时候,需要对头部以后的数据进行复制重排,所以效率很低;而 LinkedList 是基于链表实现,在添加(或删除)元素的时候,首先会通过循环查找到添加(或删除)元素的位置,如果要添加(或删除)的位置处于 List 的前半段,就从前往后找;若其位置处于后半段,就从后往前找。因此 LinkedList 添加(或删除)元素到头部是非常高效的。

同上可知,ArrayList 在添加(或删除)元素到数组中间时,同样有部分数据需要复制重排,效率也不是很高;LinkedList 将元素添加(或删除)到中间位置,是添加(或删除)元素最低效率的,因为靠近中间位置,在添加(或删除)元素之前的循环查找是遍历元素最多的操作。

而在添加(或删除)元素到尾部的操作中,我们发现,在没有扩容的情况下,ArrayList 的效率要高于 LinkedList。这是因为 ArrayList 在添加(或删除)元素到尾部的时候,不需要复制重排数据,效率非常高。而 LinkedList 虽然也不用循环查找元素,但 LinkedList 中多了 new 对象以及变换指针指向对象的过程,所以效率要低于 ArrayList。

说明一下,这里我是基于 ArrayList 初始化容量足够,排除动态扩容数组容量的情况下进行的测试,如果有动态扩容的情况,ArrayList 的效率也会降低。

END

我们已经从源码的实现角度深入了解了 ArrayList 和 LinkedList 的实现原理以及各自的特点。如果你能充分理解这些内容,很多实际应用中的相关性能问题也就迎刃而解了。

就像如果现在还有人跟你说,“ArrayList 和 LinkedList 在新增、删除元素时,LinkedList 的效率要高于 ArrayList,而在遍历的时候,ArrayList 的效率要高于 LinkedList”,你还会表示赞同吗?

希望通过这篇文章,你对它们的性能差异有了更深入的了解!如果有任何疑问或建议,欢迎在评论区留言,让我们一同学习进步!

如有疑问或者更多的技术分享,欢迎关注我的微信公众号“知其然亦知其所以然”!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/320086.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux系统SSH远程管理服务概述

目录 一.SSH协议 1.定义 2.优点 (1)加密 (2)压缩 3.SSH的客户端与服务端 (1)客户端 (2)服务端 4.原理 5.实验:使用ssh远程登录 二.OpenSSH服务器 1.概念 2.…

自动执行 Active Directory 清理

Active Directory (AD) 可帮助 IT 管理员分层存储组织的资源,包括用户、组以及计算机和打印机等设备,这有助于管理员集中创建基于帐户和组的规则,并通过创建不合规的自动日志来强制执行和确保合规性。 不时清理AD是保…

详解SpringCloud微服务技术栈:认识微服务、服务拆分与远程调用

👨‍🎓作者简介:一位大四、研0学生,正在努力准备大四暑假的实习 🌌上期文章:首期文章 📚订阅专栏:微服务技术全家桶 希望文章对你们有所帮助 在此之前,耗时半个月&#x…

哈希表的实现(2):拉链法实现哈希表

一,拉链法 在使用线性探测法实现哈希表时,会发生哈希冲突。这个时候就得向后找位置给新插入的值。这个过程无疑会对哈希表的效率有很大的影响。那我们能不能通过另一种方式来实现哈希表,让哈希表不会发生哈希冲突呢?答案当然是可以…

第二十八周:文献阅读笔记(弱监督学习)+ pytorch学习

第二十八周:文献阅读笔记(弱监督学习) 摘要Abstract1. 弱监督学习1.1. 文献摘要1.2. 引言1.3. 不完全监督1.3.1. 主动学习与半监督学习1.3.2. 通过人工干预1.3.3. 无需人工干预 1.4. 不确切的监督1.5. 不准确的监督1.6. 弱监督学习的创新点 2…

Vue-14、Vue绑定style样式

1、对象写法 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>绑定css样式</title><!--引入vue--><script type"text/javascript" src"https://cdn.jsdelivr.net/npm/v…

数据结构:堆和堆排序

数据结构&#xff1a;堆和堆排序 文章目录 数据结构&#xff1a;堆和堆排序1.二叉树的存储结构1.顺序结构2.链式结构 2.堆3.堆的实现4.堆排序&#xff08;选择排序中的一类&#xff09;1. 基本思想2.代码实现 1.二叉树的存储结构 1.顺序结构 顺序结构存储就是使用数组来表示一…

ssm基于VUE.js的在线教育系统论文

摘 要 随着学习压力越来越大&#xff0c;课外参加补习班的学生越来越多。现在大多数学生采用请家教、自学、报名补习班的方式进行课外的额外学习。请家教费用昂贵&#xff0c;自学效率低&#xff0c;碰到自己不会的知识不能及时得到解达&#xff0c;报名补习班需要时间、地点的…

TinyGPT-V:2.8B参数引领轻量级多模态AI

前言 在当前多模态大型语言模型&#xff08;MLLM&#xff09;快速发展的背景下&#xff0c;TinyGPT-V的出现标志着一个重要的技术突破。这款轻量级模型以其2.8B参数的设计&#xff0c;在AI领域引起广泛关注&#xff0c;成为GPT-4V等模型的高效替代方案。 Huggingface模型下载&…

爬虫之牛刀小试(六):爬取BOSS网站招聘的内容

今天决定再次尝试一下 selenium BOSS网站 想要找到我们感兴趣的职位&#xff0c;随便举个例子吧&#xff0c;比如家教啥的 搜一下 找到我们感兴趣的内容 接着尝试用selenium模拟登录&#xff0c;如下所示&#xff1a; 接着找到对应的位置让selenium自己干就行了。 最后的…

SSM基础入门

SSM Mybatis、Spring和SpringMVC这三个框架整合在一起完成业务功能开发 文章目录 SSM5.1 流程5.2 详细步骤5.2.1 基本配置5.2.2 功能模块开发5.2.3 测试5.2.3.1 单元测试5.2.3.2 PostMan测试 5.3 统一结果封装5.3.1 概念5.3.2 实现 5.4 统一异常处理5.4.1 异常处理器的使用5.4…

统计学-R语言-4.5

文章目录 前言多变量数据多维列联表复式条形图并列箱线图R语言中取整运算主要包括以下五种&#xff1a; 点带图多变量散点图重叠散点图矩阵式散点图 练习 前言 本篇文章将继续对数据的类型做介绍&#xff0c;本片也是最后一个介绍数据的。 多变量数据 掌握描述多变量数据的分…

openssl3.2 - 官方demo学习 - server-arg.c

文章目录 openssl3.2 - 官方demo学习 - server-arg.c概述笔记备注END openssl3.2 - 官方demo学习 - server-arg.c 概述 TLS服务器, 等客户端来连接; 如果客户端断开了, 通过释放bio来释放客户端socket, 然后继续通过bio读来aceept. 笔记 对于开源工程, 不可能有作者那么熟悉…

vue前端开发自学demo,父子组件之间传递数据demo2

vue前端开发自学demo,父子组件之间传递数据demo2!实际上&#xff0c;组件之间传递数据的&#xff0c;数据类型&#xff0c;是可以多种多样的&#xff0c;下面为大家展示几个常见的数据类型&#xff0c;比如数字类型&#xff0c;数组类型&#xff0c;对象类型。 代码如下所示&a…

sublime中添加GBK编码模式

当写代码的中文注释时&#xff0c;编译代码出现如下错误&#xff1a; 解决办法&#xff0c;添加GBK模式&#xff1a; &#xff11;. 点击Preferences -> Package Control&#xff1a; 2. 在跳出来的搜索框里搜索conver, 点击ConverToUTF8 3. File左上角会多出GBK的选项 由…

PiflowX-DorisRead组件

DorisRead组件 组件说明 从Doris存储读取数据。 计算引擎 flink 有界性 目前Doris Source是有界流&#xff0c;不支持CDC方式读取。 组件分组 Doris 端口 Inport&#xff1a;默认端口 outport&#xff1a;默认端口 组件属性 名称展示名称默认值允许值是否必填描述…

【遇见Transformer】Transformer代码、原理全方位解析,相信我,看这一篇就够了!

目录 前言 预备知识 本章代码环境 关注我&#xff0c;不迷路 &#xff01; Transformer模型的结构​编辑 Transformer模型的基本原理 注意力机制 自注意力机制 两者的区别 多头注意力机制 Transformer模型的训练 Transformer模型的应用 论文地址 前言 预备知识 在…

学习python仅此一篇就够了(文件操作:读,写,追加)

python文件操作 文件编码 编码技术即&#xff1a;翻译的规则&#xff0c;记录了如何将内容翻译成二进制&#xff0c;以及如何将二进制翻译回可识别内容。 计算机中有许多可用编码&#xff1a; UTF-8 GBK BUG5 文件的读取操作 open&#xff08;&#xff09;函数 在pyth…

数据库锁表原因、排查、解决

一.场景 场景1场景2二.原因三.排查四.解决方案 一.场景 场景1 锁表通常发生在DML&#xff08; insert 、update 、delete &#xff09; A操作进行全量数据同步&#xff0c;对整个表的粒度进行上锁&#xff0c;导致B操作只能等待A操作完成才能进入插入数据。此时就出现了锁表…

【分布式技术】监控平台zabbix介绍与部署

目录 一、为什么要做监控&#xff1f; 二、zabbix是什么&#xff1f; 三、zabbix有哪些组件&#xff1f; ​编辑Zabbix 6.0 功能组件&#xff1a; ●Zabbix Server ●数据库 ●Web 界面 ●Zabbix Agent ●Zabbix Proxy ●Java Gateway 四、zabbix的工作原理&#xf…