① 利用空参创建的集合,在底层创建一个默认长度为0的数组
② 添加第一个元素时,底层会创建一个新的长度为10的数组
③ 存满时,会扩容1.5倍
④ 如果依次添加多个元素,1.5倍还放不下.则新创建数组的长度以实际为准
ArrayList list = new ArrayList<>(); // 默认初始长度为0
list.add("aaa"); // 添加第一个元素
以下为ArrayList底层源码
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
private static final int DEFAULT_CAPACITY = 10;
transient Object[] elementData;
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
当在调用ArrayList无参构造方法时,会创建一个空的数组.其初始长度默认为0.
public boolean add(E e) {
ensureCapacityInternal(size + 1); // size目前为0
elementData[size++] = e;
return true;
}
在调用ArrayList的add方法后,传入的参数为添加的数据(这里以"aaa"为例),add方法会调用其内部的ensureCapacityInternal方法,并传入参数1(size+1)
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
// 若数组等于空数组,返回DEFAULT_CAPACITY和minCapacity中的较大的数
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// 此时的minCapacity为10,elementData.length为0
if (minCapacity - elementData.length > 0)
grow(minCapacity); // 扩容方法
}
private void grow(int minCapacity) {
// minCapacity为10
int oldCapacity = elementData.length; //0
int newCapacity = oldCapacity + (oldCapacity >> 1); //0
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity; //10
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
calculateCapacity方法返回DEFAULT_CAPACITY(10),并调用ensureExplicitCapacity方法,参数为10,ensureExplicitCapacity方法中进行判断,条件成立,调用grow方法,传入参数10.方法中进行判断,条件成立,将minCapacity(10)赋值给newCapacity.最后调用Arrays.copyOf方法复制elementData数组的数据以长度为10赋值给elementData.此时的elementData是一个长度为10的空数组.再回到add方法中,elementData[size++]=e; 将数据加进数组.
list.add("kkk"); // 添加第十一个元素
public boolean add(E e) {
ensureCapacityInternal(size + 1); // size目前为10
elementData[size++] = e;
return true;
}
在调用ArrayList的add方法后,传入的参数为添加的数据(这里以"kkk"为例),add方法会调用其内部的ensureCapacityInternal方法,并传入参数11(size+1)
private void ensureCapacityInternal(int minCapacity) {
// 这里的minCapacity为11
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
// 返回11
return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// elementData.length为10
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
// minCapacity为11
int oldCapacity = elementData.length; //10
int newCapacity = oldCapacity + (oldCapacity >> 1); // 15
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
calculateCapacity方法返回11,并调用ensureExplicitCapacity方法,参数为11,ensureExplicitCapacity方法中进行判断,条件成立,调用grow方法,传入参数11.方法中进行判断,条件不成立,最后调用Arrays.copyOf方法复制elementData数组的数据以长度为15赋值给elementData.此时已完成扩容整个过程.再回到add方法中,elementData[size++]=e; 将数据加进数组.
list1.addAll(list2); // 假设list1容量刚好为10,list2容量为100
调用方法addAll并传入参数list2
public boolean addAll(Collection extends E> c) {
Object[] a = c.toArray();
int numNew = a.length; // 100
// size此时为10
ensureCapacityInternal(size + numNew);
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0;
}
方法中调用ensureCapacityInternal 方法并闯入参数110(size+numNew)
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity; // 110
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// minCapacity 为110,elementData.length为10
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
int oldCapacity = elementData.length; // 10
int newCapacity = oldCapacity + (oldCapacity >> 1); //15
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity; //110
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
calculateCapacity方法返回110,并调用ensureExplicitCapacity方法,参数为110,ensureExplicitCapacity方法中进行判断,条件成立,调用grow方法,传入参数110.方法中进行判断,条件成立,将minCapacity(110)赋值给newCapacity.最后调用Arrays.copyOf方法复制elementData数组的数据以长度为110赋值给elementData.此时已完成扩容整个过程.再回到add方法中,System.arraycopy(a, 0, elementData, size, numNew);将数据加进原来的数组.