首先ArrayList集合底层是通过Object数组实现的。
当使用空参构造器实例化ArrayList时,底层首先会创建一个名为ElementData的Object类型数组,并使elementData等于集合中定义的为空的静态常量数组DEFAULTCAPACITY_EMPTY_ELEMENTDATA 。
transient Object[] elementData;
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
此时的elementData数组是一个空数组,没有定义数组长度
当集合首次添加数据,调用add()方法时,elementData数组会成为长度为10的数组。
分析如下:
使用add()方法向集合中添加数据时,定义数组长度的流程
1.首先创建出来的数组为空,所以size=0;
public boolean add(E e) {
ensureCapacityInternal(size + 1);
elementData[size++] = e;
return true;
}
2.上面add方法调用ensureCapacityInternal()方法时size=0,这里传入的参数minCapacity=0+1=1
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
3.刚创建出来的数组elementData为空,elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA,
则进入if语句中
参数minCapacity=1,静态常量DEFAULT_CAPACITY=10,去两个数中较大的数,则返回值为DEFAULT_CAPACITY=10
private static final int DEFAULT_CAPACITY = 10;
private static int calculateCapacity(Object[] elementData, int minCapacity) {
//如果此时数组为刚创建时的为空状态
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//private static final int DEFAULT_CAPACITY = 10;
//比较两者大小,返回较大的
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
//如果不为空,说明数组已经定义过长度,返回此时长度
return minCapacity;
}
4.这里就相当于ensureExplicitCapacity(10);
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
5.传入参数minCapacity=10,elementData.length=0
进入if语句,执行方法grow(10)
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
if (minCapacity - elementData.length > 0)
grow(minCapacity);
//grow(10);
}
6.>>运算符
按二进制形bai式把所有的数字向du右移动对应位数,低位移出(舍弃),高位的空位补符zhi号位,即正数补零,负数补1。符号位不变。
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8
private void grow(int minCapacity) {
//此时数组长度为0,oldCapacity=0
int oldCapacity = elementData.length;
//将数组长度扩大到原来的1.5倍,还是0
int newCapacity = oldCapacity + (oldCapacity >> 1);
//newCapacity - minCapacity=0-10=-10<0
if (newCapacity - minCapacity < 0)
//newCapacity=10
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//此时elementData的长度就为10
elementData = Arrays.copyOf(elementData, newCapacity);
}
所以,当集合使用空参构造器时,底层是一个空数组。当第一次调用add()方法添加数据后,底层数组就会变为长度为10的数组。
当使用有参构造器实例化ArrayList
传入参数initialCapacity大于0时,创建一个长度为initialCapacity的数组,赋值给elementData。
传入参数等于0时elementData = EMPTY_ELEMENTDATA,而EMPTY_ELEMENTDATA为Object类型的空数组。
如果其他条件(initialCapacity<0),则抛出异常。
private static final Object[] EMPTY_ELEMENTDATA = {};
public ArrayList(int initialCapacity) {
//当传入参数大于0时,创建长度为传入参数大小的数组
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
//如果传入参数为0,创建数组elementData等于定义的静态常量EMPTY_ELEMENTDATA
this.elementData = EMPTY_ELEMENTDATA;
} else {
//如果传入参数不符合规定,抛出异常IllegalArgumentException
throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);
}
}