ArrayList和LinkedList的区别

243 阅读4分钟
  1. ArrayList是基于数组实现,LinkedList是基于链表实现,当随机访问List时,ArrayList比LinkedList的效率更高,等等
  2. 使用场景:ArrayList和LinkedList在新增、删除元素时,LinkedList的效率要高于 ArrayList,而在遍历的时候,ArrayList的效率要高于LinkedList

Detail:

  1. ArrayList的实现类
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
  • ArrayList实现了List接口,继承了AbstractList抽象类,底层是数组实现的,并且实现了自增扩容数组大小。
  • ArrayList还实现了Cloneable接口和Serializable接口,所以他可以实现克隆和序列化。
  • ArrayList还实现了RandomAccess接口,这个接口是一个标志接口,他标志着“只要实现该接口的List类,都能实现快速随机访问”。

当ArrayList新增元素时,如果所存储的元素已经超过其已有大小,它会计算元素大小后再进行动态扩容,数组的扩容会导致整个数组进行一次内存复制。ArrayList 无参构造器初始化时,默认大小是空数组,并不是大家常说的 10,10 是在第一次 add 的时候扩容的数组值。

  • 添加元素:添加元素到任意位置,会导致在该位置后的所有元素都需要重新排列,而将元素添加到数组的末尾,在没有发生扩容的前提下,是不会有元素复制排序过程的。所以ArrayList在大量新增元素的场景下效率不一定就很慢的;如果我们在初始化时就比较清楚存储数据的大小,就可以在ArrayList初始化时指定数组容量大小,并且在添加元素时,只在数组末尾添加元素,那么ArrayList在大量新增元素的场景下,性能并不会变差,反而比其他List集合的性能要好。
  • 删除元素:ArrayList在每一次有效的删除元素操作之后,都要进行数组的重组,并且删除的元素位置越靠前,数组重组的开销就越大。
  • 遍历:由于ArrayList是基于数组实现的,所以在获取元素的时候是非常快捷的。
  1. LinkedList

LinkedList是基于双向链表数据结构实现的。这个双向链表结构,链表中的每个节点都可以向前或者向后追溯.

public class LinkedList
    extends AbstractSequentialList
    implements List, Deque, Cloneable, java.io.Serializable
  • LinkedList类实现了List接口、Deque接口,同时继承了AbstractSequentialList抽象类,- LinkedList既实现了List类型又有Queue类型的特点;

  • LinkedList也实现了Cloneable和Serializable接口,同ArrayList一样,可以实现克隆和序列化。 由于LinkedList存储数据的内存地址是不连续的,而是通过指针来定位不连续地址,因此,LinkedList不支持随机快速访问,LinkedList也就不能实现RandomAccess接口。

  • 节点查询: 链表查询某一个节点是比较慢的,需要挨个循环查找才行;采用了简单二分法

  • 新增元素:add (Ee)方法是将添加的元素加到队尾(将last元素置换到临时变量中,生成一个新的Node节点对象,然后将last引用指向新节点对象,之前的last对象的前指针指向新节点对象。) 如果我们是将元素添加到任意两个元素的中间位置,添加元素操作只会改变前后元素的前后指针,指针将会指向添加的新元素,所以相比ArrayList的添加操作来说,LinkedList的性能优势明显

  • 删除元素:首先要通过循环找到要删除的元素,如果要删除的位置处于List的前半段,就从前往后找;若其位置处于后半段,就从后往前找。

  • 遍历元素:在LinkedList循环遍历时,我们可以使用iterator方式迭代循环,直接拿到我们的元素,而不需要通过循环查找List。

因为LinkedList基于链表实现的,在使用for循环的时候,每一次for循环都会去遍历半个List,所以严重影响了遍历的效率; ArrayList则是基于数组实现的,并且实现了RandomAccess接口标志,意味着ArrayList可以实现快速随机访问,所以for循环效率非常高。 LinkedList的迭代循环遍历和ArrayList的迭代循环遍历性能相当,也不会太差,所以在遍历LinkedList时,我们要切忌使用for循环遍历。

来源: mp.weixin.qq.com/s/IuXnprZdz…