ArrayList扩容机制底层源码分析

79 阅读1分钟

ArrayList扩容机制底层源码分析

1、代码

public static void main(String[] args) {
    ArrayList<Integer> list = new ArrayList<>();
    for (int i = 1; i <= 10; i++) {
        list.add(i);
    }
    for (int i = 11; i <= 15; i++) {
        list.add(i);
    }
}

2、结论

首先,先说结论:

当创建ArrayList对象时,当使用无参构造器时,则初始化elementData容量为0,第一次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为原来的1.5倍

3、底层源码

3.1 第一次添加元素

首先打上断点

Snipaste_2022-08-02_13-34-12.png

步入查看构造方法

Snipaste_2022-08-02_13-34-35.png

查看DEFAULTCAPACITY_EMPTY_ELEMENTDATA属性

Snipaste_2022-08-02_13-35-45.png

也就是一个空数组,将其赋给elementData属性

Snipaste_2022-08-02_13-36-43.png

步入

Snipaste_2022-08-02_13-37-06.png

首先是执行了Integer包装类的封装

Snipaste_2022-08-02_13-37-35.png

接着进入add方法,进入ensureCapacityInternal方法

Snipaste_2022-08-02_13-38-07.png

进入calculateCapacity方法

Snipaste_2022-08-02_13-38-32.png

首先查看传进来的数组是否为空数组,很显然为true,所以返回的是DEFAULT_CAPACITY(10)与minCapacity(size + 1 = 1)的最大值,即返回10,接着进入ensureExplicitCapacity方法

Snipaste_2022-08-02_13-39-40.png

modCount为集合的操作次数,查看目前elementData.length为0,所以条件满足,进入grow方法

Snipaste_2022-08-02_13-41-02.png

oldCapacity = 0;
newCapacity = 0 + 0/2 = 0;
newCapacity - minCapacity = 0 - 10;
newCapacity = 10;

通过copyOf方法创建了一个容量为 0 ,每个元素为null的集合

Snipaste_2022-08-02_13-42-05.png

Snipaste_2022-08-02_13-37-35.png

回到该方法,将elementData[0]赋值1

size自增为1

3.2 第十一次添加元素

Snipaste_2022-08-02_13-43-40.png

主要差异在于此,此时传入的参数为11

oldCapacity = 10;
newCapacity = 10 + 10/2 = 15;
newCapacity - minCapacity = 15 - 11;
newCapacity = 15;

集合容量扩容为15