基准测试了 ArrayList 和 LinkedList ,发现我们一直用 ArrayList 也是没什么问题的
ArrayList 应该是 Java 中最常用的集合类型了,以至于我们说到集合就会自然而然的想到 ArrayList。很多同学都没有用过除了 ArrayList 之外的其他集合,甚至于都已经忘了除了 ArrayList 之外的其他集合,例如 LinkedList、Vector 等。
那么我们平时只用 ArrayList 是不是正确呢,我既然知道了 LinkedList、Vector ,是不是也要用一下它呢,那么什么情况下用呢。
Vector 是线程安全的集合类型,所以仅在多线程编程的时候才考虑是否用它,凡是为了多线程设计,必然在性能上有所损失, Vector 只是在每个方法上简单的加上 synchronized 关键字,所以性能损失是肯定的。
那么现在就来比较一下 ArrayList 和 LinkedList,都说插入、删除操作多的话用 LinkedList,插入操作多的话用 ArrayList,产生这种说法的大致依据如下。
ArrayList
内部是用 Object 数组作为存储结构,数组是内存中连续的内存空间,并且继承了 RandomAccess接口,所以可以实现元素的快速访问。但如果不是在末尾插入元素的话,需要拷贝插入位置之后的元素。
LinkedList
内部自己实现的 Node 链表,每个节点都指明了上一节点和下一节点, 所以不要求内存连续,并且插入数据只需要修改上一节点和下一节点的指针即可。但是访问元素需要遍历查找,所以查询元素较慢。
真的是这样吗?下面我做了一系列的测试,来看一下真实的情况。
插入数据
分别从头部、尾部和随机位置插入数据,初始的列表长度分别为 10、1w、10w 来测试几种插入数据的性能,以平均耗时为依据。得到的结果如下:

头部插入数据,ArrayList 耗时明显大于 LinkedList ,得出结论头部插入数据 LinkedList 性能优于 ArrayList,因为在头部位置插入数据时,ArrayList 要拷贝插入位置之后的数据,往后移动一个位置。

尾部插入数据,ArrayList 耗时小于 LinkedList,得出结论:尾部插入数据,ArrayList 性能优于 LinkedList。

随机位置是用 Random 产生的,上限是当前列表长度。可见随机位置插入数据,ArrayList 耗时小于 LinkedList ,得出结论:多次随机位置插入数据,平均性能 ArrayList 优于 LinkedList,注意,这里说的是多次随机插入求的平均值。
插入数据得出以下结论
| 插入位置 | 初始列表长度10 | 初始列表长度1w | 初始列表长度10w |
|---|---|---|---|
| 头部 | LinkedList 优于 ArrayList | LinkedList 优于 ArrayList | LinkedList 优于 ArrayList |
| 尾部 | ArrayList 优于 LinkedList | ArrayList 优于 LinkedList | ArrayList 优于 LinkedList |
| 多次随机位置 | ArrayList 优于 LinkedList | ArrayList 优于 LinkedList | ArrayList 优于 LinkedList |
获取数据
分别从头部、尾部和随机位置获取数据,初始的列表长度分别为1000、10w、100w、1000w 来测试几种获取数据的性能,以吞吐量为判断依据,吞吐量单位是 每毫秒内操作数。得到的结果如下:

头部获取数据,ArrayList 吞吐量大于 LinkedList,得出结论头部获取数据,ArrayList 性能优于 LinkedList

尾部获取数据,ArrayList 吞吐量大于 LinkedList,得出结论尾部获取数据,ArrayList 性能优于 LinkedList

多次随机位置获取数据,ArrayList 吞吐量大于 LinkedList,得出结论多次随机位置获取数据,ArrayList 性能优于 LinkedList
综上,获取数据操作的结论如下
| 获取位置 | 列表长度1000 | 列表长度10w | 列表长度100w | 列表长度1000w |
|---|---|---|---|---|
| 头部 | ArrayList 优于 LinkedList | ArrayList 优于 LinkedList | ArrayList 优于 LinkedList | ArrayList 优于 LinkedList |
| 尾部 | ArrayList 优于 LinkedList | ArrayList 优于 LinkedList | ArrayList 优于 LinkedList | ArrayList 优于 LinkedList |
| 多次随机位置 | ArrayList 优于 LinkedList | ArrayList 优于 LinkedList | ArrayList 优于 LinkedList | ArrayList 优于 LinkedList |
这是毋庸置疑的,实现了随机访问并且内部以数组形式存储数据的 ArrayList 拥有明显的优势。
删除数据
分别从头部、尾部和随机位置获取数据,初始的列表长度分别为1w、100w、1000w 来测试几种删除数据的性能,以吞吐量为判断依据,吞吐量单位是 每毫秒内操作数。得到的结果如下:

头部删除数据,LinkedList 吞吐量大于 ArrayList,得出结论:头部删除数据,LinkedList 性能优于 ArrayList

尾部删除数据,ArrayList 吞吐量大于 LinkedList,得出结论:尾部删除数据,ArrayList 性能优于 LinkedList

多次随机位置删除数据,ArrayList 吞吐量大于 LinkedList,得出结论:尾部删除数据,ArrayList 性能优于 LinkedList
综上,删除数据操作的结论如下
| 获取位置 | 列表长度100w | 列表长度1000w |
|---|---|---|
| 头部 | LinkedList 优于 ArrayList | LinkedList 优于 ArrayList |
| 尾部 | ArrayList 优于 LinkedList | ArrayList 优于 LinkedList |
| 多次随机位置 | ArrayList 优于 LinkedList | ArrayList 优于 LinkedList |
遍历数据
分别比较了 5 种遍历方式在1000、100w、1000w 长度的列表下的性能状况。
遍历方式一,原始形式的 for 循环
for(int i = 0;i<x;i++){
//do something
}
遍历方式二,增强形式的 for 循环
for(Integer i : arrayList){
// do something
}
遍历方式三,迭代器方式
Iterator iterator = arrayList.iterator();
while (iterator.hasNext()){
// do something
}
遍历方式四,forEach 方式
arrayList.forEach(integer -> {
// do something
});
遍历方式五,stream 方式
正常来讲,stream 后面再接 forEach 是不太正确的测试方式,一般 stream 都会配合 map、filter 等操作来进行筛选、计算等。这里为了方面测试,姑且先这个写了。
arrayList.stream().forEach(integer -> {
// do something
});
ArrayList 这 5 种方式遍历的性能

LinkedList 这 5 种方式遍历的性能

比较这五种方式下 ArrayList 和 LinkedList 的性能


LinkedList 只有在头部插入和删除数据频繁的时候才有优势,但是能找到这种应用场景似乎也不容易找到。如此看来,我们在程序中用到列表就随手 new 一个 ArrayList 倒也很有道理。
不要吝惜你的「推荐」呦
本文中的测试使用 JMH 基准测试完成的,图表是用 Excel 做的,如果需要源码和 Excel 文件,请在公众号内回复关键词 「jmh」
欢迎关注,不定期更新本系列和其他文章
古时的风筝 ,进入公众号可以加入交流群

基准测试了 ArrayList 和 LinkedList ,发现我们一直用 ArrayList 也是没什么问题的的更多相关文章
- 深入理解java中的ArrayList和LinkedList
杂谈最基本数据结构--"线性表": 表结构是一种最基本的数据结构,最常见的实现是数组,几乎在每个程序每一种开发语言中都提供了数组这个顺序存储的线性表结构实现. 什么是线性表? 由0 ...
- ArrayList与LinkedList比较
ArrayList与LinkedList比较 1.实现方式 ArrayList内部结构为数组,定义如下: /** * The array buffer into which the elements ...
- Java自学-集合框架 ArrayList和LinkedList的区别
ArrayList和LinkedList的区别 步骤 1 : ArrayList和LinkedList的区别 ArrayList ,插入,删除数据慢 LinkedList, 插入,删除数据快 Arra ...
- Java中ArrayList与LinkedList的区别
Java中ArrayList与LinkedList的区别 一般大家都知道ArrayList和LinkedList的区别: 1. ArrayList的实现是基于数组,LinkedList的实现是基于双向 ...
- 浅谈Vector、ArrayList、LinkedList
下图是Collection的类继承图 从图中可以看出:Vector.ArrayList.LinkedList这三者都实现了List 接口.所有使用方式也很相似,主要区别在于实现方式的不同,所以对不同的 ...
- Java基础——ArrayList与LinkedList(一)
一.定义 ArrayList和LinkedList是两个集合类,用于储存一系列的对象引用(references). 引用的格式分别为: ArrayList<String> list = n ...
- Java中ArrayList和LinkedList的性能分析
ArrayList和LinkedList是Java集合框架中经常使用的类.如果你只知道从基本性能比较ArrayList和LinkedList,那么请仔细阅读这篇文章. ArrayList应该在需要更多 ...
- Java ArrayList,LinkedList使用
1.ArrayList底层采用数组实现,当使用不带参数的构造方法生成ArrayList对象时,实际上回在底层生成一个长度为10的Object类型数组. 2.如果增加的元素个数超过10个,那么Array ...
- JAVA集合一:ArrayList和LinkedList
JAVA集合一:ArrayList和LinkedList 参考链接: HOW2J.CN 前言 这几篇博客重点记录JAVA的几个重要的集合框架:ArrayList.LinkedList.HashMap. ...
随机推荐
- 3分钟掌握GIt常用命令
一.常用命令 git config [-l] 配置 git --help 帮助 git diff 文件 比较文件修改的内容 git add . 添加当前目录所有文件到暂存区 git add --u ...
- JAVA知识点总结(五)(常用类)
第十八章:常用类 一.main方法解读: public static void main(String[] args) //当点击运行时,JVM会自动调用main方法 //public: 被JVM调用 ...
- 报表统计——java实现查询某年某月每天数据,没数据补0
一般图表绘制例如echarts等,返回数据格式都大同小异.重点是利用sql或者java实现数据格式的转型,接下来是关键部分: 1.前提:提供的工具方法——获取某月有多少天 //通过年份和月份确定该月的 ...
- Redis系列---操作命令及数据类型
本章将简单介绍下,Redis里面常用的数据类型以及我们常用到的一些命令,let's go 准备环境: Redis 详细见上一个章节 我们接下来操作的命令用的是Redis自带的客户端工具,在安装red ...
- 【MySQL】mysql5.7数据库的安装和配置
第一步:直接从官网下载安装包,.msi 可以直接点击安装..zip直接解压到目录,本人是C:\Program Files\MySQL\mysql-5.7 第二步:需要配置环境变量,我的电脑->属 ...
- JAVA之类的动手动脑
1.默认构造方法与自定义的构造方法的冲突 package com.xu; class fool { int value; fool(int nowvalue) { value=nowvalue; } ...
- Linux内存描述之内存区域zone–Linux内存管理(三)
服务器体系与共享存储器架构 日期 内核版本 架构 作者 GitHub CSDN 2016-06-14 Linux-4.7 X86 & arm gatieme LinuxDeviceDriver ...
- javascript关键字typeof、instanceof、constructor判断类型
鉴于 ECMAScript 是松散类型的,因此需要有一种手段来检测给定变量的数据类型.对于这个问题,JavaScript 也提供了多种方法,但遗憾的是,不同的方法得到的结果参差不齐. 下面介绍常用的几 ...
- python编程基础之二
交互式: 此处以windows为例:开始->运行->cmd,输入python 交互式界面 优点:即时,所见即所得 缺点:代码不可复用,根本无法进行维护 退出:exit() 代码是顺序执行: ...
- [JLOI2014]天天酷跑
请允许我对记忆化搜索进行一个总结,我认为所有的搜索只要数据范围允许,都可以转化为记忆化搜索, 只是,用处的多与少的关系,其本身是求出设出状态之后,为求出当前状态进行递推(搜索),推到 已知状态,之后再 ...