本篇主要對添加元素,和擴容機制進行分析
屬性
/**
* 序列號
*/
private static final long serialVersionUID = 8683452581122892189L;
/**
* 默認初始容量
*/
private static final int DEFAULT_CAPACITY = 10;
/**
*
* 共享的空數組用於實例空數組
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* 共享的空數組用於實例化默認大小的空數組,用於區分EMPTY_ELEMENTDATA,
* 當添加了第一元素的,數組容量擴充爲DEFAULT_CAPACITY,即10。
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* 存儲數據的數組,
*/
transient Object[] elementData; // non-private to simplify nested class access
/**
* 當前元素個數
*/
private int size;
構造方法
// 參數:initialCapacity 指定大小初始化容量
public ArrayList(int initialCapacity) {
// 初始化容量>0
if (initialCapacity > 0) {
// new Object[initialCapacity],創建指定大小的數組,並賦值給elementData
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
// 如果initialCapacity 爲0,則把EMPTY_ELEMENTDATA這個空數組,賦值給elementData
this.elementData = EMPTY_ELEMENTDATA;
} else {
// 如果initialCapacity<0,拋出異常
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
/**
* 無參構造,DEFAULTCAPACITY_EMPTY_ELEMENTDATA賦值給elementData
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
public ArrayList(Collection<? extends E> c) {
// Collection轉換爲數組,並賦值給 elementData
elementData = c.toArray();
// 如果元素個數不爲0
if ((size = elementData.length) != 0) {
// 如果c.toArray不是Object類型
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// 如果爲0,用EMPTY_ELEMENTDATA替換,賦值給elementData
this.elementData = EMPTY_ELEMENTDATA;
}
}
- ArrayList():在放入第一個元素的時候,擴容到默認大小10;
- ArrayList(int initialCapacity):創建一個initialCapacity大小的數組給elementData
- ArrayList(Collection<? extends E> c):將Collection類型的集合轉換爲數組,賦值給elementData
add(E e)
我們來看看整個add(E e)的過程
public boolean add(E e) {
// 確認容量
ensureCapacityInternal(size + 1); // Increments modCount!!
//賦值
elementData[size++] = e;
return true;
}
-------------------------------------------------------
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
/**
* 這裏就是爲甚麼 new ArrayList()默認爲10 的原因
* 用無參構造函數進行初始化的時候:
* 把DEFAULTCAPACITY_EMPTY_ELEMENTDATA賦值給了elementData
* 在第一次添加元素時進入到這裏
* 經過max計算minCapacity=10;
* 然後調用ensureExplicitCapacity擴容到10,
*
*/
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
//確認是否進行擴容
ensureExplicitCapacity(minCapacity);
}
-------------------------------------------------------
private void ensureExplicitCapacity(int minCapacity) {
// modCount:記錄操作次數,modCount++;
modCount++;
// overflow-conscious code
// 如果最小的容量-當前數組長度>0
if (minCapacity - elementData.length > 0)
// 擴容
grow(minCapacity);
}
-------------------------------------------------------
private void grow(int minCapacity) {
// overflow-conscious code
// oldCapacity 原來容量;
int oldCapacity = elementData.length;
// 新的容量 = 原來容量+原來容量/2;
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 如果新的容量-最小容量<0
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);
}
ArrayList添加元素操作,就這麼個流程,先確認是否擴容,然後在放入元素
- 如果使用new ArrayList()創建對象,第一個元素的時候,擴容到默認大小10;
- 如果是其他情況,則當size+1-elementData.length>0時(當前元素個數+1-當前容量>0),進行擴容
擴容方式:
新的容量 = 原來容量+原來容量/2: int newCapacity = oldCapacity + (oldCapacity >> 1)
這裏用到了位運算:可以參考我的另外一篇文章:位運算
add(int index, E element)
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
//這個arraycopy是native方法,大該意思大家還是能看出來;index後面的元素
// 通通後移一位
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
//插入元素
elementData[index] = element;
size++;
}