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. python正则表达式字符记录

    代码 功能 . 匹配任意1个字符(除了\n) [] 匹配[]中列举的字符 \d    匹配数字,即0-9 \D   匹配非数字, 即不是数字 \s 匹配空白,即空格,tab键 \S 匹配非空白 \w ...

  2. Intellij IDEA 2019 + Java Spring MVC + Hibernate学习笔记(1)

    之前的技术栈一直是围绕.net 做的,现在.net 技术栈的使用越来越少,越来越窄.好多原来的同事都转Java开发了. 最近公司变动,自己需要重新找个坑,压力山大.好多要求Java技术栈的根本没机会进 ...

  3. python + selenium 环境搭建及问题

    搭建平台windows 准备工具如下: ------------------------------------------------------------- 下载python https://w ...

  4. [技术栈]CRC校验原理及C#代码实现CRC16、CRC32计算FCS校验码

    1.CRC.FCS是什么 CRC,全称Cyclic Redundancy Check,中文名称为循环冗余校验,是一种根据网络数据包或计算机文件等数据产生简短固定位数校验码的一种信道编码技术,主要用来检 ...

  5. System.exit退出程序

    方法源码: /** * Terminates the currently running Java Virtual Machine. The * argument serves as a status ...

  6. layui 上传图片回显并点击放大实现

    1.页面代码布局 <div class="layui-col-xs12 form-group"> <div class="layui-col-xs6&q ...

  7. python爬虫遇到会话存储sessionStorage

    记录一次爬虫生成链接过程中遇到的sessionStorage存储数据 1.简介 sessionStorage 是HTML5新增的一个会话存储对象,用于临时保存同一窗口(或标签页)的数据,在关闭窗口或标 ...

  8. C++常用库函数(1)

    Hello,疯狂的杰克由于大家见面了哦! 今天,给大家介绍一篇很有内涵的文章:C++常用库函数 1.缓冲区操作函数 函数名:memchr 函数原型:void  *memchr(const void * ...

  9. netty源码解解析(4.0)-23 ByteBuf内存管理:分配和释放

    ByteBuf内存分配和释放由具体实现负责,抽象类型只定义的内存分配和释放的时机. 内存分配分两个阶段: 第一阶段,初始化时分配内存.第二阶段: 内存不够用时分配新的内存.ByteBuf抽象层没有定义 ...

  10. JAVA的List接口的remove重载方法调用原理

    前言 说真的,平常看源码都是自己看完自己懂,很少有写出来的冲动. 但是在写算法的时候,经常用到java中各种集合,其中也比较常用到remove方法. remove有重载函数,分别传入参数是索引inde ...