ArrayList 源码分析扩容原理

Java基础知识中面试必问的包括集合,我们不仅要掌握集合语法的使用,也要了解集合体系中每个分支的底层数据结构。掌握了这些对集合已经有了比较深入的认识,接下来就是针对具体的细节深究,本文旨在通过追踪源码带大家初次认识一下ArrayList的扩容原理

提到ArrayList,我们可以脱口而出底层数据结构是数组,但是如果被追问,刚开始的时候ArrayList存数据时候,数组容量是多少?如果存的数据超过了初始容量的大小,该怎么?-----数组扩容增大容量。 扩容的细节是什么?带着这些疑问我们往下步步探索!

创建ArrayList有两种方式,使用无参构造器和使用有参构造器,两个办法的扩容逻辑也有区别

先看结论:
无参构造器:刚开始数组容量大小为0,第一次扩容到10,第二次扩容到1.5倍-----15,第三次扩容到1.5倍------22,第四次扩容到1.5倍-----33…
有参构造器:刚开始数组容量为自定义的大小,后面为1.5倍

无参构造器创建ArrayList的演示代码(在a1处打断点调试)

@Test
    public void Test02(){
        List list = new ArrayList();
        //elementDate初始容量为0
        //第一次扩容到10
        list.add("a1");  //断点
        list.add("a2");
        list.add("a3");
        list.add("a4");
        list.add("a5");
        list.add("a6");
        list.add("a7");
        list.add("a8");
        list.add("a9");
        list.add("a10");

        //需要扩容到15
        list.add("a11");   //断点
        list.add("a12");
        list.add("a13");
        list.add("a14");
        list.add("a15");

        //第三次扩容到22
        list.add("a12");  //断点
    }

现追踪第一次扩容底层执行流程,看看如何给数组分配大小并且存数据 a1
在这里插入图片描述
在这里插入图片描述
接下来该第二次扩容了,我们先不看源码,先根据上面的逻辑自己分析一下怎么实现的。

  1. 进入add(E e)方法{ 调用执行方法ensureCapacityInternal(参数为 10+1)}
  2. 调用执行方法ensureExclicitCapacity( CaculateCapacity(10,11))
  3. 调用执行方法CaculateCapacity(10,11){
    if(11== 0)不成立 所以直接 return 11}
  4. 调用执行方法ensureCapacityInternal(参数为 11)
  5. 调用执行方法ensureExclicitCapacity( CaculateCapacity(10,11))
  6. 调用执行方法ensureExclicitCapacity(参数为11){
    if(11- 10 >0)成立--------->说明需要11个,现在只提供10个,需要扩容}
  7. 调用执行方法grow(11){
    oldCapacity =10
    newCapacity = 10 + 10/2 = 15
    if(15-11 < 0 ) 不成立-------->说明 提供的15个空间 足够 所需要的最少11个 的条件
    执行扩容方法Arrays.copyOf(10,15)
  8. 总共15个空间已经扩容结束,elementData[10]存入元素 a11

经过debug调试验证,完全符合我们的推测。

拓展:解释一下图示方法
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值