ArrayList扩容机制:源码解读

  • Post author:
  • Post category:其他


这篇文章探讨ArrayList的扩容机制,配合源码讲解,所有的讲解都在代码上注释了,清晰易懂。



其实思路很简单:



首先去扩容,扩大1.5倍。但是,扩容后的容量可能还是不够我们需要的容量,那么这时候就直接赋值成我们需要的容量大小。另外,可能扩容后,可能扩的太大了,所以我们需要通过hugeCapacity方法来保证扩容的大小是比较合理的。

public boolean add(E e) {
        ensureCapacityInternal(size + 1); // 添加一个元素前,先确保容量是否够
        elementData[size++] = e;
        return true;
}

//得到最小扩容量
private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

private static int calculateCapacity(Object[] elementData, int minCapacity) {
    //当 要 add 进第1个元素时,minCapacity为1,在Math.max()方法比较后,minCapacity 为10。
	if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {// 如果还是初始化的数组,也返回默认大小10和传入参数的最大值,不然直接返回minCapacity(size+1)
		return Math.max(DEFAULT_CAPACITY, minCapacity);
	}
	return minCapacity;
}

//判断是否需要扩容,如果需要扩容,则调用grow方法扩容
private void ensureExplicitCapacity(int minCapacity) {
	modCount++;
    if (minCapacity - elementData.length > 0)// 如果需要的容量大于现有的数组的容量大小,则进行扩容
		grow(minCapacity);
}

// 扩容核心方法
private void grow(int minCapacity) {
    /*
    将新容量大小设定为之前容量的1.5倍,如果大小还不够,将新容量大小设定为需要的容量的大小。如果新容量大小超过了定义的数组的最大容量,则通过hugeCapacity方法来重新计算新容量大小(确保每次扩容不会太大)。如果需要的容量小于0,就抛出OOM异常。不然,则将新容量设定为最大整数值或者定义的数组最大容量值。
    */
	int oldCapacity = elementData.length;// 数组现在的大小
	int newCapacity = oldCapacity + (oldCapacity >> 1);// 数组应有的新的容量大小,增加为之前的1.5倍
	if (newCapacity - minCapacity < 0) // 如果新计算得到的大小还是小于需要的大小,则令新的容量大小为需要的大小的容量
		newCapacity = minCapacity;
	if (newCapacity - MAX_ARRAY_SIZE > 0)// 如果计算得到的大小超过了List最大大小,则调用hugeCapacity函数
		newCapacity = hugeCapacity(minCapacity);// 保证每次做的扩容不会扩的太大
	elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {// 当前size=Integer.MAX_VALUE时,再添加,size+1就小于0了
	if (minCapacity < 0) // overflow 如果容量大小<0,抛出OOM  minCapacity = Integer.MAX_VALUE+x(x>0时,就OOM了)
		throw new OutOfMemoryError();
	return (minCapacity > MAX_ARRAY_SIZE) ?	// 如果最小容量超过List最大大小,则返回整数最大值,如果没有,则返回List定义的最大值
		Integer.MAX_VALUE :
		MAX_ARRAY_SIZE;
}



版权声明:本文为Elliot_Elliot原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。