成员变量源码
// 默认的初始化容量
private static final int DEFAULT_CAPACITY = 10;
// 用于空实例的共享空数组实例
private static final Object[] EMPTY_ELEMENTDATA = {};
//用于默认大小的空实例的共享空数组实例。我们将其与空元素数据区分开来,以了解何时充气添加第一个元素。
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* 存储ArrayList元素的数组缓冲区。ArrayList的容量是这个数组缓冲区的长度。当添加第一个元素时,任何
* 带//有elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA的空ArrayList都将扩展为
* DEFAULT_CAPACITY。
*/
transient Object[] elementData; // 非私有以简化嵌套类访问
/**
* ArrayList的大小(它包含的元素的数量)
*/
private int size;
构造方法1:
第一种构造方法:
/**
* 构造具有指定初始容量的list
*
* @param list的初始化容量
* @throws 如果指定的初始容量是负数就抛出IllegalArgumentException异常
*/
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
// 如果初始化容量大于0则创建一个容量为initialCapacity的动态数组
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
// 如果初始化容量等于0则设置为初始化的成员变量EMPTY_ELEMENTDATA空数组
this.elementData = EMPTY_ELEMENTDATA;
} else {
// 如果小于零则抛出非法参数异常
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
第二种构造方法:
/**
* 源码注释:创建一个初始化为10的list
* 但是DEFAULTCAPACITY_EMPTY_ELEMENTDATA是一个空的数组,这就是1.8的不点,其实它是在调用add
* 方法时添加第一个元素的时候才将list集合的初始化容量改为了10,一开始创建集合的时候它的初始化
* 容量是0
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
第三种构造方法:
/**
*构造包含指定的集合
*
* @param c the collection whose elements are to be placed into this list
* @throws
*/
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
我们来看看add()方法:到底是不是在第一次添加元素的时候才完成的初始化容量;
public boolean add(E e) {
// 确定内部容量。size代表的是list中已有的元素length
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
*此方法是上面方法中calculateCapacity的实现方法,在此方法中,if判断只有在第二种构造方法new
ArrayList()才能判断通过,通过后初识化为(DEFAULT_CAPACITY = 10)
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
// 否则返回
return minCapacity;
}
*此方法是上面方法中ensureExplicitCapacity的实现方法
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// 这里就是判断需不需要扩容,如果当前集合长度大于底层数组长度则进行扩容,进而调用下面的
// grow()方法
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
// grow()方法的实现
private void grow(int minCapacity) {
// 把数组长度赋值给老的容量
int oldCapacity = elementData.length;
// 新的数组容量 = 老的数组容量的1.5倍 oldCapacity >>1 相当于除以2
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 如果新的容量小于传入的参数容量,则新的容量等于传入的参数容量
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
// 如果新的容量大于数组容纳的最大元素个数 MAX_ARRAY_SIZE 2^{31}-1-8
// 那么在判断传入的容量是否大于数组容纳的最大元素个数,如果大于的话,那么新的数组容量则等于
// Integer.MAX_VALUE;否则等于 MAX_ARRAY_SIZE
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
这里有3个判断:
if (newCapacity - minCapacity < 0)
if (newCapacity - MAX_ARRAY_SIZE > 0)
以及hugeCapacity(minCapacity);函数中的:
(minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
意义为:当重新计算的容量(x1.5那个计算)小于传入要求容量参数,那么新的容量则按照新传入的容量为基准;
当传入容量参数太大,大到超过了数组的容量限定值却又小于整数限定值 -1,那么新的数组容量以整数限定值 -1为准,但是当传入的容量参数不大于数组的容量限定值时,以容量限定值为准;