成員變量源碼
// 默認的初始化容量
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爲準,但是當傳入的容量參數不大於數組的容量限定值時,以容量限定值爲準;