1.初始容量
在源码中,ArrayList根据传递参数的不同有三种不同的构造方式
- 传递一个整数 新创建集合大小等于传递的整数大小
- 空参构造 新创建集合大小为空
- 传递集合 新创建集合大小等于传递的参数集合大小
源码如下:
//1.传递一个整数
public ArrayList(int initialCapacity) {if (initialCapacity > 0) {this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {this.elementData = EMPTY_ELEMENTDATA;} else {throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);}}//空集合
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};//2.空参构造
public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}//3.传递一个集合
public ArrayList(Collection<? extends E> c) {Object[] a = c.toArray();if ((size = a.length) != 0) {if (c.getClass() == ArrayList.class) {elementData = a;} else {elementData = Arrays.copyOf(a, size, Object[].class);}} else {// replace with empty array.elementData = EMPTY_ELEMENTDATA;}}
2.扩容机制
当我们空参构造一个ArrayList集合,此时集合大小为空。那么当我们添加第一个元素时,就会触发扩容。在第一次扩容时,集合大小为从空扩容为10。
此时我们继续向集合内添加元素,当添加10个元素时,此时集合已经满了,那么当我们继续添加元素时,就会第二次的触发扩容。在第二次扩容时,集合大小由10变为了15,也就是原集合的1.5倍。
当我们继续添加时,达到15个元素时,再次添加就会触发第三次扩容。如果每次都是扩容原集合大小的1.5倍,此时15*1.5是个小数,那扩容多大呢。通过底层可以发现,底层的1.5倍是,先在原来大小的基础上右移一位,也就是先取出来原先的一半,在加在原来的容量大小上。所以,在第三次扩容时,首先 15>>1 = 7(位运算)15 + 7 = 22.所以容量此时变为了22。
通过模拟发现扩容的规律为
[0, 10, 15, 22, 33, 49, 73, 109, 163, 244, 366, 549, 823, 1234, 1851, 2776, 4164, 6246, 9369, 14053, 21079, 31618, 47427, 71140, 106710, 160065, 240097, 360145, 540217, 810325, 1215487]
但是ArrayList的扩容机制比我们想象的要复杂的多。前面我们是一个元素一个元素加入的,使用的add方法。
我们可以看一下源码
private Object[] grow(int minCapacity) {int oldCapacity = elementData.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);} else {return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];}}public static int newLength(int oldLength, int minGrowth, int prefGrowth) {// preconditions not checked because of inlining// assert oldLength >= 0// assert minGrowth > 0int prefLength = oldLength + Math.max(minGrowth, prefGrowth); // might overflowif (0 < prefLength && prefLength <= SOFT_MAX_ARRAY_LENGTH) {return prefLength;} else {// put code cold in a separate methodreturn hugeLength(oldLength, minGrowth);}}private static int hugeLength(int oldLength, int minGrowth) {int minLength = oldLength + minGrowth;if (minLength < 0) { // overflowthrow new OutOfMemoryError("Required array length " + oldLength + " + " + minGrowth + " is too large");} else if (minLength <= SOFT_MAX_ARRAY_LENGTH) {return SOFT_MAX_ARRAY_LENGTH;} else {return minLength;}}
源码分析,待补充。。。