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 也是没什么问题的的更多相关文章

  1. 深入理解java中的ArrayList和LinkedList

    杂谈最基本数据结构--"线性表": 表结构是一种最基本的数据结构,最常见的实现是数组,几乎在每个程序每一种开发语言中都提供了数组这个顺序存储的线性表结构实现. 什么是线性表? 由0 ...

  2. ArrayList与LinkedList比较

    ArrayList与LinkedList比较 1.实现方式 ArrayList内部结构为数组,定义如下: /** * The array buffer into which the elements ...

  3. Java自学-集合框架 ArrayList和LinkedList的区别

    ArrayList和LinkedList的区别 步骤 1 : ArrayList和LinkedList的区别 ArrayList ,插入,删除数据慢 LinkedList, 插入,删除数据快 Arra ...

  4. Java中ArrayList与LinkedList的区别

    Java中ArrayList与LinkedList的区别 一般大家都知道ArrayList和LinkedList的区别: 1. ArrayList的实现是基于数组,LinkedList的实现是基于双向 ...

  5. 浅谈Vector、ArrayList、LinkedList

    下图是Collection的类继承图 从图中可以看出:Vector.ArrayList.LinkedList这三者都实现了List 接口.所有使用方式也很相似,主要区别在于实现方式的不同,所以对不同的 ...

  6. Java基础——ArrayList与LinkedList(一)

    一.定义 ArrayList和LinkedList是两个集合类,用于储存一系列的对象引用(references). 引用的格式分别为: ArrayList<String> list = n ...

  7. Java中ArrayList和LinkedList的性能分析

    ArrayList和LinkedList是Java集合框架中经常使用的类.如果你只知道从基本性能比较ArrayList和LinkedList,那么请仔细阅读这篇文章. ArrayList应该在需要更多 ...

  8. Java ArrayList,LinkedList使用

    1.ArrayList底层采用数组实现,当使用不带参数的构造方法生成ArrayList对象时,实际上回在底层生成一个长度为10的Object类型数组. 2.如果增加的元素个数超过10个,那么Array ...

  9. JAVA集合一:ArrayList和LinkedList

    JAVA集合一:ArrayList和LinkedList 参考链接: HOW2J.CN 前言 这几篇博客重点记录JAVA的几个重要的集合框架:ArrayList.LinkedList.HashMap. ...

随机推荐

  1. AppBoxFuture: Raft快照及日志截断回收

      AppBoxFuture的存储引擎依赖Raft一致性协议来保证各个分区副本的一致性,如果不处理Raft日志将不断增长,因此需要特定的机制(定期或每处理一定数量的日志)来回收那些无用的日志数据.通过 ...

  2. 2019-ccpc秦皇岛现场赛

    https://www.cnblogs.com/31415926535x/p/11625462.html 昨天和队友模拟了下今年秦皇岛的区域赛,,,(我全程在演 题目链接 D - Decimal 签到 ...

  3. SQL使用UPDATE和SUBSTRING截取字符串方法,从头截取到某个位置,截取中间片段,字符串中间截取到末尾或删除前面的字符串

    //从头截取 update 表名 set 表列名 =SUBSTRING(表列名,1,目标位置数值)  //!计数从1开始,从左往右 where 条件   //条件自己选择,不加where条件会更新所有 ...

  4. navicat工具 pymysql模块

    目录 一 IDE工具介绍(Navicat) 二 pymysql模块 一 IDE工具介绍(Navicat) 生产环境还是推荐使用mysql命令行,但为了方便我们测试,可以使用IDE工具,我们使用Navi ...

  5. 阿里云DLA工具 查询tablestore数据

    OTS和DLA元信息映射逻辑 字段的映射关系 OTS DLA INTEGER(8bytes) bigint(8bytes) STRING varchar BINARY varbinary DOUBLE ...

  6. PID算法的理解及场景模拟

    增量式PID算法的简化版之后的公式: △u(t)=Ae(t)-Be(t-1)+Ce(t-2) △u:PID控制器输出的下一时刻的调整量 e(t):PID控制器在当前时刻的状态变化量-给定值 e(t-1 ...

  7. 你也可以写聊天程序 - C# Socket学习1

    简述 我们做软件工作的虽然每天都离不开网络,可网络协议细节却不是每个人都会接触和深入了解.我今天就来和大家一起学习下Socket,并写一个简单的聊天程序. 一些基础类 首先我们每天打开浏览器访问网页信 ...

  8. html5视频常用API接口

    一.虽然有的属性是boolean类型,但仍旧建议按照XHTML书写(属性名=”属性值”)格式,避免出现错误 (下面加粗的属性为常用属性) 属性 值 功能描述 controls controls 是否显 ...

  9. python编程基础之五

    转义字符:就是不方便从键盘之间输出,或者是原字符有特殊含义的一些字符, 下面列举几个常用的转义字符 \',\",\''',\""",\\,都是表示原字符的意思, ...

  10. TP框架配合jquery进行3种方式的多图片上传

    用的TP5.1框架+jquery 一 使用form表单方式进行多图片上传 html代码: <form action="../admin/admin/cs" enctype=& ...