ArrayList源码学习

概述:ArrayList是java的一个集合类,实现的是List接口。List接口下的实现类所表示的集合具有有序可重复的特点。下面通过对一段测试代码进行debug来分析add方法的工作原理以及ArrayList是怎么扩容的。
在这里插入图片描述
debug运行后在13行停住,此时我们step into 进入ArrayList的空参构造方法里去,看到以下代码:
在这里插入图片描述
这里是将DEFAULTCAPACITY_EMPTY_ELEMENTDATA赋值给elementData,这两个是ArrayList中定义的两个空的对象数组

transient Object[] elementData;
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

其中elementData就是添加元素的数组(从这可以知道ArrayList底层就是一个对象数组)。

接着我们再step over进入第一个for循环,我们重点关注第一次添加时和添加第十一个元素时add方法是怎么运行的。
当添加第一个元素时我们step into:
在这里插入图片描述
此时因为i是基本数据类型int,所以要进行装箱成Integer类型。这不是我们关注的重点,我们step out再次step into进入到add方法里:
在这里插入图片描述
可以看到,此时添加的元素e=1,而方法第一步执行的ensureCapacityInternal方法(该方法作用是在添加元素前判断数组是不是已经满了,如果是的话就会扩容):
在这里插入图片描述
这个方法调用一个ensureCapacityInternal方法,传入参数为calculateCapacity方法的返回值,进入calculateCapacity方法:
在这里插入图片描述
由于此时elementDate还是空数组,所以进入到第一个if语句中,返回DEFAULT_CAPACITY和mincapacity两者更大那个。前者是10,后者是size+1也就是1,所以返回的是10即mincapacity,接着进入到ensureExplicitCapacity方法中:
在这里插入图片描述
方法第一行表示修改次数modCount加一,接着判断第一个if语句是否成立,minCapacity=10,elementData.length=0,条件成立进入到if语句执行grow方法,这就是ArrayList的扩容方法:
在这里插入图片描述
第一步:将elementData数组大小赋给oldCapacity,表示数组以前的大小。

第二步:将oldCapacity的1.5倍赋给newCapacity,表示数组现在的大小。

但是,此时数组大小为0,扩容1.5倍还是0

第三步:if语句条件成立,将minCapacity赋给newCapacity(为10),后两个if语句条件不成立,执行到方法的最后,方法的最后就是实现扩容的方法,调用Arrays的copyof方法,这个方法的作用是保留数组已有数组,增加数组的容量。

从这我们可以知道在第一次添加元素时,ArrayList会进行扩容,第一次扩容的大小为10。

在添加第2个一直到第10的元素时,

if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }

上述代码就不会执行了,因为数组已经不是空数组了,所以minCapacity每次就是size+1即数组在这次添加后已有元素个数

 if (minCapacity - elementData.length > 0)
            grow(minCapacity);

那么上述代码也就不会执行了,即不需要进行扩容。

一直让代码运行到第17行,也就是添加第十一个元素时:
在这里插入图片描述
首先进入到add方法中,流程还是和之前一样,我们直接跳到最关键的一步开始:
在这里插入图片描述
此时minCapacity(11) - elementData.length(10) > 0,所以要第二次进行扩容:

minCapacity表示已有元素个数包括此次添加的元素(因为是先判断再添加该元素),

它暗指最小需要多大容量的数组。

如果它比数组容量大的话,说明数组装不下,那么就需要进行扩容了。
在这里插入图片描述
还是和之前一样数组以前的大小赋给oldCapacity,将oldCapacity的1.5倍赋给newCapacity,表示数组现在的大小。和之前那次不同(之前那次oldCapacity=0,所以1.5倍相当于没变),这次不是0,此时newCapacity为oldCapacity的1.5倍=15,最后调用Arrays的copyof方法实现1.5倍扩容。

总结:当用ArrayList的空参构造方法生成list数组时,在添加第一个元素时,会将数组从0扩容到到10,之后在每一次数组满时,再添加元素会先进行1.5倍的扩容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值