ArrayList 与 LinkedList 性能对比

5 阅读1分钟

新增元素

从头部插入
ArrayList从集合头部位置新增元素花费的时间595
LinkedList从集合头部位置新增元素花费的时间15
涉及到数组复制

从中间插入
ArrayList从集合中间位置新增元素花费的时间1
LinkedList从集合中间位置新增元素花费的时间101

从尾部插入
ArrayList从集合尾部位置新增元素花费的时间69
LinkedList从集合尾部位置新增元素花费的时间193

ArrayList 在添加元素的时候如果不涉及到扩容,性能在两种情况下(中间位置新增元素、尾部新增元素)比 LinkedList 好很多,只有头部新增元素的时候比 LinkedList 差,因为数组复制的原因。

当然了,如果涉及到数组扩容的话,ArrayList 的性能就没那么可观了,因为扩容的时候也要复制数组

删除元素

ArrayList

ArrayList 删除元素的时候,有两种方式,一种是直接删除元素(remove(Object)),需要直先遍历数组,找到元素对应的索引;一种是按照索引删除元素(remove(int)

但从本质上讲,都是一样的,因为它们最后调用的都是 **fastRemove(Object, int)** 方法

从源码可以看得出,只要删除的不是最后一个元素,都需要数组重组。删除的元素位置越靠前,代价就越大

LinkedList

LinkedList 删除元素的时候,有四种常用的方式:

  • **remove(int)**,删除指定位置上的元素

先检查索引,再调用 node(int) 方法( 前后半段遍历,和新增元素操作一样)找到节点 Node,然后调用 unlink(Node) 解除节点的前后引用,同时更新前节点的后引用和后节点的前引用

  • **remove(Object)**,直接删除元素

也是先前后半段遍历,找到要删除的元素后调用 unlink(Node)

  • **removeFirst()**,删除第一个节点

删除第一个节点就不需要遍历了,只需要把第二个节点更新为第一个节点即可

  • **removeLast()**,删除最后一个节点

删除最后一个节点和删除第一个节点类似,只需要把倒数第二个节点更新为最后一个节点即可

可以看得出,LinkedList 在删除比较靠前和比较靠后的元素时,非常高效,但如果删除的是中间位置的元素,效率就比较低了

从集合头部删除元素时,ArrayList 花费的时间比 LinkedList 多很多;

ArrayList从集合头部位置删除元素花费的时间380

 LinkedList从集合头部位置删除元素花费的时间4

从集合中间位置删除元素时,ArrayList 花费的时间比 LinkedList 少很多;

ArrayList从集合中间位置删除元素花费的时间381

 LinkedList从集合中间位置删除元素花费的时间5922

从集合尾部删除元素时,ArrayList 花费的时间比 LinkedList 少一点。

ArrayList从集合尾部位置删除元素花费的时间8

LinkedList从集合尾部位置删除元素花费的时间12

遍历 LinkedList 的时候,千万不要使用 for 循环,要使用迭代器。

也就是说,for 循环遍历的时候,ArrayList 花费的时间远小于 LinkedList;迭代器遍历的时候,两者性能差不多

LinkedList用for循环遍历性能差的原因 : 因为每一次外层的 for 循环,都要执行一次 node(int) 方法进行前后半段的遍历

迭代器只会调用一次 **node(int)** 方法,在执行 list.iterator() 的时候:先调用 AbstractSequentialList 类的 iterator() 方法,再调用 AbstractList 类的 listIterator() 方法,再调用 LinkedList 类的 listIterator(int) 方法