Java集合之List——ArrayList与LinkedList比较

Java集合之List——ArrayList与LinkedList比较

实现方式

种类 实现方式 接口 父类
ArrayList 数组 List<E>, RandomAccess, Cloneable, java.io.Serializable AbstractList<E>
LinkedList 双向链表 List<E>, Deque<E>, Cloneable, java.io.Serializable AbstractSequentialList<E>

使用场景

种类 使用场景
ArrayList 随机访问、修改
LinkedList 随机位置增加、删除

空间分析

种类 具体分析
ArrayList 因为有扩容操作,在尾部预留有额外空间,每次扩容为150%,会造成一定的空间浪费
LinkedList 虽然没有浪费空间,但是每个元素都存储在Node对象中,每个元素相比于ArrayList多了两个引用域next、prev,因此占用空间比ArrayList

性能分析

操作 ArrayList LinkedList
get(index) O(1) O(n)
add() O(1) O(1)
add(index) O(n) O(n)
remove() O(n) O(n)

分析:可以发现,LinkedListadd(index)、remove()方法的时间复杂度也是O(n),这是因为在增删操作之前需要先得到增删元素的位置,然后才能进行增删,然而LinkedList只能通过遍历来得到位置,得到位置之后的具体操作复杂度才是O(1),因此操作的时间复杂度为O(n)。

  • 末端插入:虽然二者都是O(1),但是还是有一定差别,当集合中数据还不多时,由于ArrayList扩容机制调用比较频繁,消耗时间较多,所以相较而言LinkedList更快;随着元素地增多ArrayList扩容机制调用越来越少,消耗时间会越来越少,而对于每次LinkedList而言,每次插入都要new一个对象,相对而言消耗时间较为稳定。因此,当数据量小时,LinkedList速度快,随着数据量的增加,ArrayList速度更快。
  • 随机插入:LinkedList对于随机插入有一个优化,当插入位置在前半部分时从头遍历,当插入位置在后半部分时,从尾遍历。在前半段随机插入,一般来说,由于ArrayListSystem.arraycopy耗时多,此时的LinkedList效率高于ArrayList;而在后半段随机插入,此时很难判断,因为在后半段,ArrayList元素挪动消耗减少,而对于LinkedList来说效率不变,因此二者的性能相差不大。

    总结

    只有当频繁在List前端位置进行增删操作,才选用LinkedList。一般情况,都会更倾向于选用ArrayList