JAVA中ArrayList和LinkedList常用方法性能分析
概述
众所周知,ArrayList和LinkedList都实现了List接口,ArrayList是基于数组实现的,查询快,增删慢;LinkedList是基于链表实现的,查询慢,增删快。但实际上这种说法是不准确的,容易产生歧义,让很多人以为频繁向集合中插入元素的情景下时就不能用ArrrayList,这是不对的。笔者接下来通过数据结构、测试验证、结果分析三个步骤来展示二者性能上的差异。
说明:性能分析都是在大量数据的情况下讨论的话题,不再赘述。
我先解释一下文中会出现的几个符号,以便于接下来的陈述:
index取值说明: 0-第一个元素 last-最后一个元素 center-中间的元素,eg:
add(0,E):在元素集的首位插入元素E
get(center):获取中位元素
remove(last):删除最后一个元素
数据结构
什么是数据结构
数据结构由逻辑结构和存储结构组成,可以这样理解:
数据结构 = 逻辑结构 + 存储结构
逻辑结构决定了基本运算的定义。分为线性结构、非线性结构等。
存储结构决定了具体的算法。分为顺序存储、链式存储等。
数据结构与List关系
知道了这些,就很好理解ArrayList和LinkedList的关系了:
找到影响性能的“元凶”
顺序存储增删慢在何处?链式存储查询又慢在何处呢?
顺序存储
在指定对位置添加元素时,在该位置后面的元素都需要向后移动一个位置。同样,删除指定位置的元素时,在该位置后面的元素都需要向前移动一个位置。元素的移动次数导致顺序存储增删慢的主要因素。
链式存储
链式存储,查询时不能像顺序存储那样通过元素的索引来查找元素,它一般会遍历集合中所有元素进行匹配查询。因此,元素的遍历是导致链式存储慢的主要因素。
测试验证
在实际开发中,我们经常用到List的add()、remove()、get()三个方法。接下来对这三个方法进行测试。
测试说明
数据量:1000W
数据类型:Integer
JDK版本:1.8
用例:add(E),remove(0),remove(last),get(last),get(center)
测试代码
package com.wyh.ds.test.util;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class ListTest {
public static final int LENGTH = 10000000;
public static void main(String[] args) {
new Thread(() -> {
List<Integer> linked = new LinkedList<Integer>();
long t1 = System.currentTimeMillis();
for(