ArrayList扩容机制

ArrayList是Java中的一种动态数组,它在添加元素时会进行扩容。初始容量为10,扩容策略是1.5倍。当需要的容量超过现有容量,它会使用grow方法以1.5倍当前容量或所需容量的较大值进行扩容。如果超过Integer.MAX_VALUE,会进行特殊处理以防止溢出。
摘要由CSDN通过智能技术生成

  

首先可以确定的是ArrayList的底层是数组形式,ArrayList有序且元素不重复,查询效率高,增删效率低。

ArrayList的初始容量为10(当数组中没有添加元素时,初始的容量为0;i =1 时,数组的容量变为10),然后使用Arrays.copyOf方法把老数组里面的数据拷贝到新的数组里面,ArrayList为自动容量扩充选择扩充1.5倍,核心源码如下:

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;
}

 

当第一次向ArrayList集合中添加元素时,调用add方法,调用函数ensureCapacityInternal确保ArrayList当中的数组长度能够满足需求,不然数组会报数组下标越界异常之后。下面我们进入ensureCapacityInternal方法,这个方法是用来确认底层数组大小是否够用来存放数据,如果不够就需要进行扩容,如上图⬆

可以发现上面会进行判断数组是不是一个空数组,因为第一次无参构造创建ArrayList集合底层就是一个空数组,所以如果发现是一个空数组,那么扩容elementData大小为10 下面还需要进入ensureExplicitCapacity方法去判断是否需要真的扩容:

假设现在插入第11个元素,但是只有10个空间,就进入grow()方法,触发扩容;最后回到add()方法进行添加元素。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值