你知道java集合ArrayList和LinkedList的区别吗?

时间:2021-11-14 19:35:04

前言:ArrayListLinkedList  是List接口下两个最常用的实现类,也是面试时,面试官最爱问的两个集合类,你确定你对这两个类真的掌握了吗?如果没有请认真看完这篇博客!

     ArrayList: Ok,讲这个我们先从底层数据机构开始,首先ArrayList底层是基于数组实现的,学过数据结构的应该都知道,数组属于线性表中的顺序结构的线性表,物理表现即为内存为连续的空间。那么既然是数组结构,那么java在定义数组的时候需要指定数组长度,那ArrayList的默认长度是多少呢?请看下面从源码中的截图。

你知道java集合ArrayList和LinkedList的区别吗?

Ok,它的默认初始化长度为10;同时它也是支持动态扩容的,底层调用的就是 Arrays.copyOf(elementData, newCapacity),通过这个方法进行动态扩容新增加的容量大小为原容量大小的50%,具体算法如下图:

你知道java集合ArrayList和LinkedList的区别吗?

好的这里我们来说到另外一个重要的点,ArrayList是非线程安全的,为什么是非线程安全的呢,如果两个线程同时对这个列表对象进行添加操作,假设已经添加了9个元素了,两个线程各自在插入一个元素

你知道java集合ArrayList和LinkedList的区别吗?

此时这个扩容判断没有拦截住两个线程,因为还没有填充数据等到了真正填充数据的这行代码时:

你知道java集合ArrayList和LinkedList的区别吗?

两个线程运行到这行代码时,A线程先添加,B在添加,这个时候有可能造成数组越界或者是B覆盖了线程A的元素,这个时候取决于两个线程的时间差,如果时间差足够短那么必然覆盖了A添加的元素,时间差不是那么短的情况下,B可以感应到Size的变化时候这个时候就是数组越界了!

  LinkedList  : 它的底层数据结果是链表参考源码,可知该链表是双向链表,即可以从头遍历到尾,也可以从尾遍历到头。

你知道java集合ArrayList和LinkedList的区别吗?

同样它也是线程不安全的,在这里最可能的造成的并发原因就是链表成环,很多人不理解为什么会成环这里我详细说明下,以该LinkedList 类的linkFirst(E e)方法为例下面是源代码:

你知道java集合ArrayList和LinkedList的区别吗?


好的同样假设有两个线程A,B且链表非空,A线程此时创建节点后赋予首节点,在还没有将节点f的前驱节点修改A创建的节点的时候, 此时B线程new了一个节点,来作为开始节点,这个时候节点f于是将B的节点作为了它的前驱节点,于是造成了成环,这里本来就比较抽象,希望大家好好理解一下!!!

   总结:

     (1)ArrayList和LinkedList都是非线程安全的!

      (2)由于LinkedList是基于链表的数据结构在做链表之间插入数据 或删除数据会比较方便,但是查询会比较垃圾,因为需要根据开始节点或者尾节点逐步遍历。而它的缺点是ArrayList的优点,优点又同样是ArrayList的缺点!

    (3)综上就可以根据你的业务逻辑进行适当的选取,当读多的时候采取ArrayList,插入和删除多的话选取LinkedList!