LXX的网络日志
人因梦想而伟大
ArrayList源码剖析(三):数组扩容以及元素拷贝

基于Eclipse Adoptium jdk-11.0.13.8-hotspot,对ArrayList的源码进行分析

ArrayList里面最关键的一块,如果数组填充满了之后,如何进行扩容。

grow(minCapacity)方法

grow()方法

使用Arrays.copyOf方法,把newCapactity()方法计算出来newCapacity,作为新数组的长度。

所以,关键扩容的代码就在newCapacity()方法里面

newCapacity(minCapacity)方法

newCapacity()方法

下面这一行代码:

int newCapacity = oldCapacity + (oldCapacity >> 1);

oldCapacity 一开始等于0的话,计算出来的newCapacity也是0。

如果oldCapacity的大小假设是10的话,oldCapacity >> 1 计算出来的结果是5,然后再用oldCapacity + 5,也就是10+5。

新的容量也就是15。

然后就是下面这一大坨代码:

if (newCapacity - minCapacity <= 0) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
    return minCapacity;
}

newCapacity - minCapacity <= 0的,有三种情况:

(1)容量还没初始化,然后用Math.max()来判断一下,是DEFAULT_CAPACITY大还是minCapacity,然后返回最大的那个作为新的容量
(2)容量要超过最大的限制了,这个时候没办法再扩容,只能抛出异常
(3)newCapacity太小,还没有minCapacity大,这个时候就返回minCapacity作为新的容量

最后这行代码:

return (newCapacity - MAX_ARRAY_SIZE <= 0)
            ? newCapacity
            : hugeCapacity(minCapacity);

最后就是,计算出来的newCapacity,没有超过MAX_ARRAY_SIZE(Integer.MAX_VALUE - 8),也就是数组最大的容量,就返回计算出来的newCapacity作为新的容量。

hugeCapacity(minCapacity)方法

如果超过了数组最大的容量,就会去调用hugeCapacity()方法,重新获得容量:

hugeCapacity()方法

这个方法没什么好说的,最大容量就是Integer.MAX_VALUE。