【源码阅读】ArrayList扩容机制
版本:jdk17
扩容核心方法grow()
private Object[] grow(int minCapacity) {
int oldCapacity = elementData.length;
if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
int newCapacity = ArraysSupport.newLength(oldCapacity,
minCapacity - oldCapacity, /* minimum growth */
oldCapacity >> 1 /* preferred growth */);
return elementData = Arrays.copyOf(elementData, newCapacity);
} else {
return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
}
}
-
方法接收一个参数
minCapacity
,表示需要的最小容量。 -
首先,通过
int oldCapacity = elementData.length;
获取当前数组的容量。 -
进入条件判断,如果满足以下任一条件:
-
oldCapacity > 0
(当前数组容量大于 0) -
elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA
(elementData
不等于默认空数组)
说明当前数组不为空,需要进行扩容操作。
-
-
在需要扩容的情况下,通过
ArraysSupport.newLength
方法计算出新的容量newCapacity
。该方法使用了之前分析的newLength
方法,根据当前容量、期望的最小增长量(minCapacity - oldCapacity
)和期望的优先增长量(oldCapacity >> 1
)来计算新的容量。 -
使用
Arrays.copyOf
方法将原数组elementData
复制到新的容量newCapacity
的新数组中,并将其赋值给elementData
。 -
如果条件判断不满足,即当前数组为空,那么根据
DEFAULT_CAPACITY
和minCapacity
的较大值来创建一个新的容量。 -
返回更新后的
elementData
数组。
计算新数组长度ArraysSupport.newLength()
public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
// preconditions not checked because of inlining
// assert oldLength >= 0
// assert minGrowth > 0
int prefLength = oldLength + Math.max(minGrowth, prefGrowth); // might overflow
if (0 < prefLength && prefLength <= SOFT_MAX_ARRAY_LENGTH) {
return prefLength;
} else {
// put code cold in a separate method
return hugeLength(oldLength, minGrowth);
}
}
private static int hugeLength(int oldLength, int minGrowth) {
int minLength = oldLength + minGrowth;
if (minLength < 0) { // overflow
throw new OutOfMemoryError(
"Required array length " + oldLength + " + " + minGrowth + " is too large");
} else if (minLength <= SOFT_MAX_ARRAY_LENGTH) {
return SOFT_MAX_ARRAY_LENGTH;
} else {
return minLength;
}
}
-
方法接收三个参数:
oldLength
表示当前数组的长度,minGrowth
表示最小增长量,prefGrowth
表示期望增长量。 -
首先,通过
int prefLength = oldLength + Math.max(minGrowth, prefGrowth);
计算出期望的新长度prefLength
。这里使用了Math.max
方法,取minGrowth
和prefGrowth
中较大的一个作为增长量。 -
在接下来的判断中,检查
prefLength
是否满足以下条件:-
大于 0
-
小于等于
SOFT_MAX_ARRAY_LENGTH
(一个常量,可能代表了数组最大允许的长度)
-
-
如果
prefLength
满足上述条件,则返回prefLength
作为新的数组长度。 -
如果
prefLength
不满足条件,说明可能存在溢出或超出允许的最大长度。在这种情况下,会调用hugeLength
方法来处理。 -
hugeLength
方法可能用于处理特别大的数组长度,但在提供的代码中并未给出具体实现。