先说结论吧:
有参构造比如说一开始就设置的容器大小是3,那么后面扩容就会以3为基底,每次增幅:前一个容量大小的50%。
那么对于初始化容量大小的3而言,第一次扩容就会增加到3 + 3 / 2 = 3 + 1 = 4,容量大小=4;
第二次为4 + 4 / 2 = 6。后面以此类推。这里其实只要看过【ArrayList有参构造源码解读】以及【ArrayList无参构造添加元素源码解读】就知道了。
下面来深入源码探究下:
debug案例:
@Test
public void testArrayListConstructor(){
ArrayList<Integer> arrayList = new ArrayList<>(3);
for (int i = 0; i <20; i++) {
arrayList.add(i);
}
}
这里直接定位到add方法这一行吧。
过程一
先判断是否为null
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
这里判断确实是在[-128,127]之间。和【ArrayList无参构造添加元素源码解读】一样,就不详细赘述了。
过程二
1、来到ArrayList的add方法:
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
和【ArrayList无参构造添加元素源码解读】一样,扩容机制就在ensureCapacityInternal这个函数里面。
2、来到ensureCapacityInternal
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
然后来到calculateCapacity
这个方法很重要,为什么每次都以前一个容量大小的一半为增幅,就是因为有参构造指定了初始容量大小,使得elementData不为空Object数组:
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
后面的过程就和【ArrayList无参构造添加元素源码解读】的一样了,除了初始容量大小不是10之外,其他都一样。
心得:
无参构造第一次扩容是10,有参构造最开始的扩容是有参构造初始容量。
其他的扩容过程都一样。