
ArrayList有三个构造方法
1.ArrayList()
ArrayList arrayList = new ArrayList();
分析:
/**
* Constructs an empty list with an initial capacity of ten.创建空集合,初始容量10
* transient Object[] elementData;集合存元素的变量
* private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};默认空容量对象
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
//调用空构造器的时候,会将elementData赋值为空对象数组。
//此时添加元素,调用add(E e)方法。
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
//添加元素之前会确认容量,调用ensureCapacityInternal方法
private void ensureCapacityInternal(int minCapacity) { ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); }
//第一次调用的时候,minCapacity = size + 1 (size第一次添加时为0,因此minCapacity = 0 + 1 = 1)
//调用此方法calculateCapacity(elementData, minCapacity)
//该方法计算最小容量值
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//第一次添加时,满足条件
return Math.max(DEFAULT_CAPACITY, minCapacity);//得到最小容量,即minCapacity = 10
}
return minCapacity;
}
//ensureExplicitCapacity(10),这里的参数为上一步计算得到的最小容量值10
private void ensureExplicitCapacity(int minCapacity) {
modCount++;//记录修改次数,主要用于多线程 provide fail-fast iterators
// overflow-conscious code
if (minCapacity - elementData.length > 0) //此时,elementData.length第一次添加时为0
grow(minCapacity); //进行扩容
}
//此方法为真正扩容方法,此时 minCapacity = 10
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length; //记录旧集合的元素个数,此时为0
//在旧容量的基础上,扩容1.5倍(右移1位相当于/2)
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0) //第一次的时候集合元素为空,newCapacity = 0,
newCapacity = minCapacity; //newCapacity = 10 第一次扩容,容量为10
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); //进行数组拷贝,扩容为10
}
//扩容完成以后,容量为10,第一个元素被添加进去

//此后继续添加元素时,重复以上方法,在添加的元素数量未达到容量10时,不会进行扩容操作
//即以下判断不成立
if (minCapacity - elementData.length > 0)
grow(minCapacity);
//直到添加第11个元素,即添加的数量超过当前集合的容量时,该if判断条件成立,进入grow(minCapacity)方法,此时minCapacity = 11
// minCapacity = 11,该方法为真正扩容方法
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length; //旧容量记录
int newCapacity = oldCapacity + (oldCapacity >> 1); //新容量扩容为旧容量的1.5倍
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:
//进行扩容,将原来数组的元素拷贝到新数组,扩容为原来的1.5倍
//实际调用的扩容方法为:System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
elementData = Arrays.copyOf(elementData, newCapacity);
}
//此后,添加的逻辑相似,当添加的元素数量又大于当前容量时扩容1.5,以此类推。
2.调用有参构造函数 ArrayList arrayList = new ArrayList(8);
分析:
/**
* Constructs an empty list with the specified initial capacity.
*
* @param initialCapacity the initial capacity of the list
* @throws IllegalArgumentException if the specified initial capacity
* is negative
* private static final Object[] EMPTY_ELEMENTDATA = {};
*/
public ArrayList(int initialCapacity) { // initialCapacity = 8
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity]; //构造一个初始容量的Object数组
} else if (initialCapacity == 0) { //如果构造函数的参数为0,则赋值为空对象数组
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
//执行添加方法,逻辑和无参构造走的方法一模一样
//只不过调用到这里的时候elementData不是空数组,而是初始容量为构造参数值 = 8的对象数组
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //条件不成立
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity; //这里返回8 minCapacity = 8
}
//之后的逻辑与无参构造执行的添加逻辑一样,也是先确认是否需要扩容,然后再执行其他操作,只不过现在的扩容是在8(构造参数中的值)的基础上扩容1.5倍。
本文详细分析了ArrayList的两种构造方法,重点讲解了无参和有参构造时对初始容量的处理,以及添加元素时的容量调整策略,包括`ensureCapacityInternal`和`calculateCapacity`方法的使用。
7255

被折叠的 条评论
为什么被折叠?



