arraylist 的扩容机制_辨析ArrayList和LinkedList

ba80d971c4adab93abdbf2f969a639a1.png

今天来看一下平时用的比较多的另外两种结构,ArrayListLinkedListArrayList是基于动态数组的结构,为什么说它是动态的呢?因为它是可以扩容的,怎么扩容我们后面再说。而LinkedList是基于链表结构的。

ArrayList

还是老样子,先贴几个常量出来,后面遇到的话有个印象

    // 默认容量  
    private static final int DEFAULT_CAPACITY = 10;
    // 空数组1
    private static final Object[] EMPTY_ELEMENTDATA = {};

    // 空数组2
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    // 数据
    transient Object[] elementData; // non-private to 

话不多说,先上图。

d43ff4153df855b58351eef10605f743.png

首先还是先new一个ArrayList, 那么我们先来看一下有哪些构造方法

c04bc0e39cae89e3d00d8112e1cd002f.png

还有一种构造方法用的不多,这里主要看这两个。一个是指定初始容量的,一个没有指定初始容量。很简单,指定初始容量的就直接创建对应容量大小的数组即可,如果确定容量的话,建议使用该构造方法,不然后面扩容很费时间。第二种就是不指定初始容量的,可以看到它仅仅是给this.elementData赋了一个空数组,并没有分配空间。咦 ,有点奇怪,没有分配空间,指定容量,我们怎么添加数据。别急,我们继续往下看。

d9c919fce5930cf0044cdaac65dc4c57.png

491e6c56af0d82355c1aa10ea53d1e2c.png

我们首先add了数据1,在add方法中,调用了ensureCapacityInternal方法, 又在ensureCapacityInternal中先后调用了calculateCapcityensureExplicitCapacity方法,顺序按照上图的123。下面简单说一下这三个函数的作用。

calculateCapcity是返回最小满足要求的最小容量的。这里我们看到了前面提过的DEFAULTCAPACITY_EMPTY_ELEMENTDATA常量,它是一个默认容量的空数组,在我们没有指定初始容量时返回的,在该方法中就会对我们是否指定了初始容量进行一个判断。

紧接着执行了ensureExplicitCapacity,这个方法本身并没有什么,重要的是在它内部调用了一个grow方法,它就是ArrayList的扩容机制。 看下它是怎么扩容的

4e16a49d5127cb083924340ac48d35fb.png

重要的其实只有两部分,上面我标1的就是扩容后的新容量,也就是旧容量的1.5倍。确定了新容量大小之后呢,就在内存中寻找一段满足要求的、连续的内存,把旧数据数组复制过去,添加新的内容,回收旧的数组空间。这是过程很耗时。

ArrayList的大致内容就是这些了,还有一些什么setremove方法,基本思想都差不多,有兴趣的可以去看看源码。 下面简单介绍一下LinkedList

LinkedList

LinkedList本质就是一个链表,无论是操作还是性能,都与我们平常所说的差不多,需要注意的是:它的底层是一个双向链表

5a565fdc834e93a8f961f8edb4a5d1cc.png

每个Node对象中不仅当前节点的元素,还包含LinkedList中它前一个和后一个的元素,每添加一个元素,就要创建一个Node对象。

前面说了这么多内容,那么ArrayListLinkedList到底有什么区别呢?它们又分别适用于哪些应用场景呢?

总结

  1. ArrayList是基于数组的,因此访问操作,它的性能要优于LinkedList,直接通过索引即可;而LinkedList则要一个个节点遍历,直到找到对应的数据。但是在中间添加或删除元素它的时间复杂度为O(n),因为这要将所操作元素后面的元素整体往后挪动或整体往前挪动;而LinkedList是基于链表的,只需要改动节点的指向即可,复杂度为O(1)。对于在结尾添加或删除,两者的性能是相同的。
  2. 对于ArrayList来说,它的空间浪费主要体现在列表的末尾留有一定的容量空间;而LinkedList则体现在它每创建一个元素,都要耗费一定的空间。
  3. ArrayList应用在查询较多,但插入和删除比较少的场景中;LinkedList主要用在查询少,而插入和删除较多的场景。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值