一、通过无参构造器构造ArrayList
1、第一次调用add方法时
//通过无参构造器构造Arraylist集合,并向集合中添加数据
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list.add(2);
}
list.add(2);
/**
transient Object[] elementData;
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
1、调用底层无参构造器创建一个空数组赋给elementData
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
/**
private int size;
2、当第一次调用add方法的时候会先调用ensureCapacityInternal方法
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
// 最后先进行赋值,然后size再++操作
elementData[size++] = e;
return true;
}
// 3、调用ensureExplicitCapacity方法,此时minCapacity为1
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
/**
private static final int DEFAULT_CAPACITY = 10;
4、计算容量,如果elementData 为空数组的话那么就返回DEFAULT_CAPACITY为10,否则返回
minCapacity。就是判断最小容量,第一次添加的时候会给一个初始10的容量.(无参构造器第一
次添加的时候符合这种条件,有参的只有当参数为0的时候第一次添加的时候符合条件)
elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
*/
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
/**
5、确保明确的容量,如果最小容量大于数组的长度,那么进行扩容,真正的扩容的方法grow()
*/
private void ensureExplicitCapacity(int minCapacity) {
modCount++; //记录修改次数的变量
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
/**
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
6、真正进行扩容的方法
*/
private void grow(int minCapacity) {
// 先将数组的长度用oldCapacity 记录起来
int oldCapacity = elementData.length;
// 再计算一个新的容量用老容量 + 老容量的1.5倍用newCapacity记录起来
int newCapacity = oldCapacity + (oldCapacity >> 1);
/** 如果新容量小于最小的容量,此时minCapacity为10,newCapacity为0,那么就将最小容量赋
给新容量此时为10
*/
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
// 如果新容量超过最大容量,那么会进行拷贝
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);
}
2、第二次调用add方法时
// 1、第二次调用add方法,此时size为1
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
// 2、调用ensureCapacityInternal方法,此时minCapacity为2
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
// 3、计算容量,这时因为不是第一次添加,所以条件不成立,直接返回最小容量2
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
// 4、进行判断是否需要扩容,minCapacity 为2,elementData.length为10,所以不需要扩容,直接返回
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
3、当容量超过10,第11次调用add方法时
// 1、第11次调用add方法时
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
// 2、此时minCapacity为11
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
// 3、计算容量,直接返回11,该判断只有第一次调用add方法时才会调用,就是第一次初始化容量,后续添加
都不会判断直接返回。
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
// 4、这步就是判断是否需要扩容的一步,此时minCapacity 为11,elementData.length为10,需要扩容,
进入grow方法。
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
// 5、进行扩容,此时newCapacity为15
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 创建一个新的实例数组赋予新的长度,并将内容进行拷贝
elementData = Arrays.copyOf(elementData, newCapacity);
}
此时ArrayList 的容量为10 + 10 *0.5 = 15
二、通过有参构造器构造ArrayList
1、第一次调用add方法时
// 通过有参构造器构建ArrayList 并向集合中添加元素
List<Integer> list = new ArrayList<>(12);
for (int i = 0; i < 12; i++) {
list.add(2);
}
list.add(2);
// 1、调用有参构造器构建集合
public ArrayList(int initialCapacity) {
// 如果容量大于0,构建一个该容量的数组,如果等于0就将空数组赋给elementData,否则抛出异常,
不合法的容量
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
// 2、第一次调用add方法时,此时size为0
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
// 3、调用ensureCapacityInternal方法,此时minCapacity为1
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
// 4、计算容量,直接返回最小容量minCapacity为1
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
// 5、判断是否需要扩容最小容量minCapacity 为1,数组长度elementData.length为12,所以不需要扩容
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
2、第二次到第12次调用add方法都和第一次调用add方法一样,当容量达到12,第13次调用add方法时
// 1、第13次调用add方法时
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
// 2、调用ensureCapacityInternal方法,此时minCapacity为13
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
// 3、计算最小容量,直接返回minCapacity13
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
// 4、判断是否需要扩容此时minCapacity为13,elementData.length为12,需要扩容调用grow方法
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
// 5、进行扩容
private void grow(int minCapacity) {
// overflow-conscious code
// oldCapacity 为 12
int oldCapacity = elementData.length;
// newCapacity 为 12 + 12 * 0.5 = 18
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 创建一个新的实例数组赋予新的长度,并将内容进行拷贝
elementData = Arrays.copyOf(elementData, newCapacity);
}
此时ArrayList 的容量为12 + 12 * 0.5 = 18
三、个人总结
1、通过无参构造器构建ArrayList集合时,会构建一个长度为0的空数组。第一次添加add方法会迎来首次扩容,初始扩容为10个长度,当达到10个长度之后,会进行第二次扩容,扩容为原来容量的1.5倍,以此类推
2、通过有参构造器构建ArrayList集合时,如果参数容量为0,那么扩容机制和通过无参构造器构建ArrayList集合是一样的。如果参数容量大于0时,会构建一个长度为参数容量的数组,当容量达到参数容量的时候会迎来首次扩容,以参数容量的1.5倍进行扩容,以此类推。如果参数容量小于0,则会报错。