ArrayList 与LinkedList 源码分析,效率比较

ArrayList 与LinkedList 源码分析,比较

ArrayList , LinkedList都是 List接口的实现类, ArrayList 底层是一个Object数组, LinkedList是一个双向链表,他们都是线程不安全的

ArrayList

先看看变量吧:
elementData : ArrayList数据的存放位置, 一目了然,是一个Object数组, 修饰符 transtient 的作用是使得该变量不能再被序列化
存放数据的位置
DEFAULT_CAPACITY : ArrayList的默认容量,初始化时若没有显示指定容量, 默认为 10 , 在 ensureCapacityInternal 方法中设置默认容量
默认容量
size : 当前该ArrayList的大小, 实际存储的数据量,注意与ellmentData数组的长度区别 , 是不一样的
size
modCount : 这是ArrayList的 父类AbstractList类中定义的变量,表示结构修改的次数, 当并发时, 若modCount不一致,触发快速失败

然后我们知道,java数组创建之后长度是固定的, 一直往数组里添加元素,数组下标会越界,这就需要对数组进行扩容

扩容时机: list的容量(Object数组的长度 ) < 需要存储的数据量。
下图代码中, minCapacity 指的是当前需要存储的数据量(size + 1),
时机
扩容大小: 1.5倍, 如果新的数组大小大于 该ArrayList最大容量时,就更新为 MAX_ARRAY_SIZE。 下图关键代码 :
newCapacity = oldCapacity + (oldCapacity >> 1) , >> : 位运算,往右移动一位,
扩容方法
扩容方法: Arrays.copyOf() , 重新申请内存,再赋值给elementData,该方法使用 System类的arraycopy() (这是一个native方法)移动数据, 操作内存,整体移动数据,效率高,包括插入,删除操作的移动数据也是使用该arraycopy方法

LinkedList

底层是一个双向链表,节点 结构如下:next 指向下一个节点, prev指向前一个,
节点结构
维护了两个引用,first 指向链表的第一个节点, last指向最后一个, 因为是链表 ,所以不存在扩容,直接插入即可节点结构
node(int index) 判断 index 靠近左边还是右边从更近的地方开始移动

ArrayList, LinkedList 查询效率比较:
ArrayList 是 Object数组实现的,可以直接通过下标随机查找, 时间复杂度 是O(1),
LinkedList 底层是双向链表, LinkedList 需要从 头或尾节点 移动到指定的节点,时间复杂度为 O (n), 所以 ArrayList的查询效率高

插入,删除效率比较:
具体需要分情况讨论: (请注意,这里的效率比较,都默认数据量很大的情况)

操作尾部, ArrayList, LinkedList 效率差不多,都可以直接插入

操作首部,LinkedList 效率高 ,可以直接插入,主要时间开销是,生成节点的时间, ArrayList (Object数组)需要移动操作位置后的元素,扩容也需要时间

操作非首尾部元素时, ArrayList效率高 , 因为 ArrayList 虽然需要移动数据,但,使用的是 System.arraycopy() (native方法)操作内存,整体移动,效率高, LinkedList 需要从 头或尾节点 移动到指定的节点再操作,效率低, 并且数据量越大,差距越明显

for, 增加for(forEach),迭代器遍历效率比较:
ArrayList: 三种遍历方式的效率都差不多 ,时间复杂度都是 O(N)

LinkedList : 迭代器 、forEach遍历方式,效率比普通 for循环效率高很多,因为普通for,每次获取元素(get方法)都需要从头部或尾部,移动到指定的元素,这会产生 O(N)的时间复杂度,所以说,for循环遍历,时间复杂度达到了 O(N * N),而 迭代器、forEach方式遍历时间复杂度为O(N)

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
ArrayListLinkedList都是Java中的集合类,用于存储一组对象。它们的主要区别在于内部实现方式不同,因此它们的性能和适用场景也有所不同。 1. 内部实现方式 ArrayList是基于动态数组实现的,底层使用数组来存储元素。在添加或删除元素时,需要对数组进行扩容或缩容,可能会导致数组的拷贝操作。 LinkedList是基于双向链表实现的,每个节点包含前驱节点和后继节点的引用。在添加或删除元素时,只需要修改节点的引用即可,不需要进行数组的拷贝操作。 2. 访问效率 ArrayList的访问效率LinkedList高,因为它是基于数组实现的,可以通过下标直接访问元素。而LinkedList需要从头或尾开始遍历链表,访问元素的时间复杂度为O(n)。 3. 插入和删除效率 LinkedList的插入和删除效率ArrayList高,因为它只需要修改节点的引用,不需要进行数组的拷贝操作。而ArrayList在插入或删除元素时,可能需要对数组进行扩容或缩容,导致时间复杂度为O(n)。 4. 内存占用 LinkedList的内存占用比ArrayList高,因为每个节点需要存储前驱节点和后继节点的引用。而ArrayList只需要存储元素本身,不需要额外的空间。 综上所述,当需要频繁地进行插入和删除操作时,可以选择使用LinkedList;当需要频繁地访问元素时,可以选择使用ArrayList。但是需要注意,在多线程环境下,ArrayListLinkedList都不是线程安全的,需要进行同步操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值