ArrayList扩容机制:源码解读

这篇文章探讨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;
}

 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
ArrayList扩容机制源码如下: ```java private void ensureCapacityInternal(int minCapacity) { // 如果当前容量不足,则需要进行扩容操作 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { // 如果当前容量是默认值,则需要将其扩容为默认容量或者minCapacity minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } private void ensureExplicitCapacity(int minCapacity) { modCount++; // 如果需要进行扩容,则进行扩容操作 if (minCapacity - elementData.length > 0) grow(minCapacity); } private void grow(int minCapacity) { // 当前容量 int oldCapacity = elementData.length; // 扩容后的容量 int newCapacity = oldCapacity + (oldCapacity >> 1); // 如果扩容后的容量仍然小于需要的最小容量,则直接使用需要的最小容量 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; // 如果扩容后的容量超过了ArrayList最大容量,则进行特殊处理 if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // 创建新的数组,并将原数组中的元素复制到新数组中 elementData = Arrays.copyOf(elementData, newCapacity); } private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; } ``` 在上述代码中,`ensureCapacityInternal`方法首先判断当前容量是否足够,如果不足,则调用`ensureExplicitCapacity`方法进行扩容操作。`ensureExplicitCapacity`方法会比较需要的最小容量和当前容量的差值,如果超过了当前容量,则进行扩容操作。`grow`方法是扩容的核心方法,它会首先计算扩容后的容量,然后根据扩容后的容量创建新的数组,并将原数组中的元素复制到新数组中。如果扩容后的容量超过了ArrayList最大容量,则进行特殊处理。`hugeCapacity`方法用于计算需要的最大容量,如果超过了最大容量,则抛出OutOfMemoryError异常。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进击的Coder*

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值