ArrayList底层其实是一个object类型的数组elementData
ArrayList提供了三种构造方法
// 1. 无参构造
public ArrayList()
// 2. 指定容量大小
public ArrayList(int initialCapacity)
// 3. 指定元素来创建
public ArrayList(Collection<? extends E> c)
调用无参时候的源码
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
其中elementData就是ArrayList实现的object的数组名,在用无参构造的时候给了一个空的数组,也就是长度为0
当第一次添加元素,扩充长度到10,此后如果继续添加元素到第11个的时候触发第二次扩充,扩容容量为本身加上自己的1.5倍,到15个,添加到16的时候扩容到22个,以此类推。
有参构造指定容量大小
有参构造的源码是如果指定的容量大于0,创建出来的ArrayList就是指定的长度,如果小于0,则抛出一个异常
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);
}
}
如果添加元素超过了有参构造指定的长度那么和无参构造扩容的机制一样,以后每次扩容都是扩容后的容量 = 原始容量 + 原始容量*0.5
指定元素创建
参数直接传入一个集合来创建一个ArrayList
初始的容量和传入集合的里面元素的个数相同,扩充规则和上面的都一样
以上这种扩容都是在add()方法添加单个元素时的扩容方法。
当addAll()传入一个集合或者多个元素进去的时候的机制是在默认下次扩容后容器的大小和当前所有的元素数量进行比较,在两者之间选择一个大的值作为容器的大小。
例如:
ArrayList<String> list = new ArrayList<String>();
//第一次添加了10个元素,此时的容量为10
list.addAll(Arrays.asList("0","1","2","3","4","5","6","7","8","9"));
//如果用的是add()方法添加元素,扩容机制同上,都是 容量=容量*1.5,也就是扩容到了15
// list.add("10");
//使用addAll再添加一个8个元素的集合
//此时的容量为18,原来的容量会先扩容一次到15然后进行比较选取之间较大者
//所以addAll的扩容或的容器为18
list.addAll(Arrays.asList("1","2","3","4","5","6","7","8"));
总结一下就两种扩容方式:
1.add()如果原始容量是0,则扩容后的容量为10,以后每次扩容都是之前的1.5倍
2.addAll()会在下次扩容的大小和当前元素数量之间选择一个较大值