ArrayList
ArrayList底层维护了一个 Object[] elementData
数组以及n int size
属性,elementData储存了元素对象,size属性为elementData数组的长度以及下次存储元素的索引位置。所以ArrayList本质上是一个动态数组,需要动态扩容机制才能满足不断添加元素的需求。
ArrayList的扩容机制:
- 当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第一次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍
- 如果直接使用指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容为elementData为1.5倍(多数情况下)
ArrayList的无参构造函数
无参构造其实是为 elementData
赋值了一个默认的空数组,DEFAULTCAPACITY_EMPTY_ELEMENTDATA
,所以当使用无参构造器初始化时,他的初始容量为0.
ArrayList的有参构造函数
分析源码可知,最终会指定elementData的长度为形参长度(输入值合法)
ArrayList的扩容机制
使用无参构造器初始化ArrayList时,第一次执行add()方法时,最终会进入到grow()方法来判断是否进行扩容,oldCapacity为0,elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA,所以最后会执行 return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)]
,最后返回一个长度为10的数组。
当第十一次执行add()方法,执行到 s==element.length
,判断出需要扩容,最终会落入到以下代码。
if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
int newCapacity = ArraysSupport.newLength(oldCapacity,
minCapacity - oldCapacity, /* minimum growth */
oldCapacity >> 1 /* preferred growth */);
return elementData = Arrays.copyOf(elementData, newCapacity);
}
- >>2 相当于/2
- ArraysSupport.newLength()方法用计算新数组的长度确保扩容时既能满足所需的最小容量 (
minCapacity
),又不会超出最大允许的数组大小 (MAX_ARRAY_SIZE
,即Integer.MAX_VALUE - 8
)。
规则:newLength = oldLength + Math.max(minGrowth, prefGrowth)
所以新数组的大小最终为15,原数组大小*1.5 倍。
分析源码可知,只有当原数组的长度为1、2或者3时,新数组的长度才会是原数组的长度+1
评论区