ArrayList扩容源码解读(自用复习)

前言:arrayList不是在创建时扩容,是在第一次add方法添加元素时才进行扩容,第一次为10,后续扩容为当前的1.5倍

debug进new ArrayList()源码中查看
将一个空数组赋给当前数组(arraylist底层是数组,就是这个elementData)
在这里插入图片描述

"DEFAULTCAPACITY_EMPTY_ELEMENTDATA"为一个空数组
在这里插入图片描述
然后进入到第一次执行add方法中
执行到ensureCapacityInternal(size为定义的一个int型变量,默认为0,这里表示的是当前add了多少个元素)
在这里插入图片描述
进入到ensureCapacityInternal中,if判断当前数组是否为一个空数组,为空的话执行Math.max(),这个方法是将两个参数做一个三元表达式,DEFAULT_CAPACITY为10,是arraylist第一次扩容大小。执行完后当前所需最小容量minCapacity为10.
在这里插入图片描述
执行到ensureExplicitCapacity方法中,判断当前所需最小容量减去当前数组大小,大于0则表示需要扩容,grow()方法内部就是扩容实现
在这里插入图片描述
第一行将原数组大小存入oldCapacity中
第二行是确定扩容大小,newCapacity是新数组大小,oldCapacity >> 1右移一位,÷2(相加后为原来的1.5倍),当前oldCapacity为0,所以newCapacity也为0
第三行判断新数组大小减去最小容量大小,进入if体内
第四行直接将新数组大小赋为当前最小需要容量为10(这里就是arraylist第一次扩容为10的原因
第五行是用当前新数组大小减去integer最大值的大小(MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;)防止数组大小超过最大值
第七行将老数组中的元素赋给新数组中,新数组容量为原来的1.5倍(第一次add容量为10)
在这里插入图片描述
执行完后将add的值添加进数组中返回,第一次数组扩容完成。
在这里插入图片描述


由于第一次add的容量为10,这里在添加到11个元素的时候看看内部实现
在这里插入图片描述
运行到ensureCapacityInternal方法由于当前不是空数组了,所以直接执行ensureExplicitCapacity
在这里插入图片描述
可以看到第二行代码中oldCapacity>>1运算出来为5,加上oldCapacity的10为15,扩容为原来的1.5倍
在这里插入图片描述
扩容1.5倍第一次是15,第二次就是15+(15/2)=22
在这里插入图片描述

ArrayListJava中常用的动态数组实现类,它可以自动扩容以容纳更多的元素。下面我们来看一下ArrayList扩容源码。 首先,ArrayList内部维护了一个数组elementData,用于存储元素。当我们向ArrayList中添加元素时,如果元素个数已经达到了数组的容量,就需要对数组进行扩容。下面是ArrayList扩容的核心代码: ```java private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { 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; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); elementData = Arrays.copyOf(elementData, newCapacity); } ``` 在ensureCapacityInternal方法中,首先判断当前的elementData是否是默认空数组,如果是,则将minCapacity与默认容量DEFAULT_CAPACITY取最大值。这是因为默认空数组的容量为0,如果minCapacity小于DEFAULT_CAPACITY,就会直接使用默认容量。如果不是默认空数组,则直接调用ensureExplicitCapacity方法。 在ensureExplicitCapacity方法中,首先将modCount加1,表示对ArrayList进行了一次修改。然后判断需要扩容的最小容量是否大于当前数组的容量,如果是,就调用grow方法进行扩容。 在grow方法中,首先将当前数组的容量oldCapacity扩大1.5倍,得到新的容量newCapacity。然后判断新容量是否小于需要的最小容量,如果是,就将新容量设置为需要的最小容量。最后再判断新容量是否超过最大数组容量MAX_ARRAY_SIZE,如果超过,就调用hugeCapacity方法抛出异常。 最后,通过调用Arrays.copyOf方法将原数组elementData复制到新数组中,完成扩容。 总体来说,ArrayList扩容过程就是先判断是否需要扩容,然后计算新容量,最后将原数组复制到新数组中。需要注意的是,ArrayList扩容策略是每次扩容1.5倍,而不是每次扩容一个固定的值。这是因为这种策略可以在大多数情况下减少扩容次数,提高性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值