面试题答案
一键面试ArrayList扩容机制源码分析
- 关键属性
elementData
:是一个Object
类型的数组,用于存储ArrayList中的元素。size
:记录ArrayList中实际元素的数量。DEFAULT_CAPACITY
:默认初始容量,值为10。
- 扩容触发时机
- 当向ArrayList中添加元素时,如果
size
达到了elementData
数组的容量(即size == elementData.length
),就会触发扩容。例如,调用add(E e)
方法时:
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; }
- 当向ArrayList中添加元素时,如果
- 具体操作步骤及关键方法
ensureCapacityInternal
方法:- 首先调用
calculateCapacity
方法来确定所需的最小容量。
private static int calculateCapacity(Object[] elementData, int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { return Math.max(DEFAULT_CAPACITY, minCapacity); } return minCapacity; }
- 然后调用
ensureExplicitCapacity
方法,该方法会检查所需的最小容量是否大于当前数组的容量,如果是,则调用grow
方法进行扩容。
private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); }
- 首先调用
grow
方法:- 计算新的容量,新容量为旧容量的1.5倍(
int newCapacity = oldCapacity + (oldCapacity >> 1);
,oldCapacity >> 1
相当于oldCapacity / 2
)。
private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); }
- 如果新容量仍然小于所需的最小容量
minCapacity
,则将新容量设置为minCapacity
。 - 如果新容量超过了
MAX_ARRAY_SIZE
(Integer.MAX_VALUE - 8
),则调用hugeCapacity
方法来处理。hugeCapacity
方法会根据minCapacity
是否大于MAX_ARRAY_SIZE
,返回Integer.MAX_VALUE
或者MAX_ARRAY_SIZE
。 - 最后通过
Arrays.copyOf
方法将旧数组的内容复制到新的、容量更大的数组中,完成扩容。
- 计算新的容量,新容量为旧容量的1.5倍(
综上所述,Java中ArrayList的扩容机制通过一系列方法协同工作,在元素数量达到数组容量时,以1.5倍的方式增加容量,并复制旧数组内容到新数组,以保证ArrayList能继续存储更多元素。