ArrayList源码剖析(三):数组扩容以及元素拷贝
基于Eclipse Adoptium jdk-11.0.13.8-hotspot,对ArrayList的源码进行分析
ArrayList里面最关键的一块,如果数组填充满了之后,如何进行扩容。
grow(minCapacity)方法
使用Arrays.copyOf方法,把newCapactity()方法计算出来newCapacity,作为新数组的长度。
所以,关键扩容的代码就在newCapacity()方法里面
newCapacity(minCapacity)方法
下面这一行代码:
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()方法,重新获得容量:
这个方法没什么好说的,最大容量就是Integer.MAX_VALUE。