ArrayList實現了List介面,它的底層資料結構是陣列,因此獲取容器中任意元素值的時間複雜度為O(1),新增或刪除元素的時間複雜度為O(N)。每一個ArrayList例項都有一個capacity變數,capacity是ArrayList用於儲存元素的容器大小,當有新元素新增到容器時,capacity會自動擴容,當新增元素時,容器會計算需要擴容的大小,減少了記憶體重新分配的次數。需要注意的時,ArrayList是非執行緒安全的容器,在多執行緒環境下容易出現執行緒安全問題。
原始碼
成員變數
private static final int DEFAULT_CAPACITY = 10; // 預設的容量是10
private static final Object[] EMPTY_ELEMENTDATA = {}; //初始化容量為0時的空陣列
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //初始化沒有指定容量
transient Object[] elementData; //儲存元素的陣列
private int size; //容器中元素的數量
構造方法
public ArrayList(int initialCapacity) {
//如果初始化指定容量 > 0,直接建立一個陣列
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; //預設的陣列容量大小是10
}
新增元素
public boolean add(E e) {
modCount++;
add(e, elementData, size);
return true;
}
private void add(E e, Object[] elementData, int s) {
//容器元素數量等於陣列的長度觸發擴容條件
if (s == elementData.length)
//呼叫grow方法進行擴容
elementData = grow();
elementData[s] = e;
size = s + 1;
}
//擴容邏輯,先計算出需要擴容的大小,再把原陣列元素拷貝到擴容後的陣列
private Object[] grow(int minCapacity) {
int oldCapacity = elementData.length;
if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
int newCapacity = ArraysSupport.newLength(oldCapacity,
minCapacity - oldCapacity, /* minimum growth */
oldCapacity >> 1 /* preferred growth */);
return elementData = Arrays.copyOf(elementData, newCapacity);
} else {
return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
}
}
private Object[] grow() {
return grow(size + 1);
}
//計算擴容後的陣列長度
public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
// preconditions not checked because of inlining
// assert oldLength >= 0
// assert minGrowth > 0
int prefLength = oldLength + Math.max(minGrowth, prefGrowth); // might overflow
if (0 < prefLength && prefLength <= SOFT_MAX_ARRAY_LENGTH) {
return prefLength;
} else {
// put code cold in a separate method
return hugeLength(oldLength, minGrowth);
}
}
通過原始碼可知,新增元素前,先判斷當前容器大小與陣列長度,決定是否要擴容,否則直接新增到容器中。擴容需要計算出擴容後新陣列的長度,新陣列長度是原陣列的1.5倍大小。
在指定位置新增元素
public void add(int index, E element) {
//先判斷插入位置是否合法
rangeCheckForAdd(index);
//記錄容器被修改的次數
modCount++;
final int s;
Object[] elementData;
//擴容條件
if ((s = size) == (elementData = this.elementData).length)
elementData = grow();
//將後面的元素後移,騰出位置
System.arraycopy(elementData, index,
elementData, index + 1,
s - index);
elementData[index] = element;
size = s + 1;
}