一、簡介
上圖爲ArrayList的繼承樹,可看出實現了四個接口,分別介紹一下:
- Serializable:是一個空接口,實現了該接口的類可序列化和反序列化
- Cloneable:是一個空接口,實現該接口的類覆蓋了clone()方法,表明該類的實例對象能被克隆
- RandomAccess:是一個空接口,表明該類的實例對象支持隨機訪問
- List:表明該類是一個列表,具有增加、刪除、修改、遍歷等功能
二、源碼分析
1. ArrayList的屬性
// 默認初始化容量爲10
private static final int DEFAULT_CAPACITY = 10;
// 空數組實例
private static final Object[] EMPTY_ELEMENTDATA = {};
// 當使用默認初始化容量時創建的空數組實例
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
// 存放元素的數組
// 當 elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
// 將第一個元素存入ArrayList時該數組會擴容至容量爲10
transient Object[] elementData;
// ArrayList的實際大小,即存放的元素數量
private int size;
// ArrayList允許存放的最大元素數
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
2. 構造方法
// 默認構造函數,使用默認初始化容量10,存放元素的數組指向一個空數組,
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
// 傳入一個初始化容量值,將存放元素的數組大小設置爲該值
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
// 傳入一個集合
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// 集合非空時則將集合的元素複製至數組
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// 傳入的集合爲空時指向一個空數組
this.elementData = EMPTY_ELEMENTDATA;
}
}
3. 增加元素
// 將元素添加到數組末尾
public boolean add(E e) {
ensureCapacityInternal(size + 1); // 判斷是否需要擴容,後面詳細講
elementData[size++] = e;
return true;
}
// 將元素添加到指定位置
public void add(int index, E element) {
rangeCheckForAdd(index); // 檢查是否越界
ensureCapacityInternal(size + 1);
System.arraycopy(elementData, index, elementData, index + 1,
size - index); // 將index開始的元素向後移一位
elementData[index] = element;
size++;
}
// 將集合所有元素添加至列表末尾
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew); // Increments modCount
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0;
}
// 將集合元素添加至指定位置
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew); // Increments modCount
int numMoved = size - index;
if (numMoved > 0)
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved);
System.arraycopy(a, 0, elementData, index, numNew);
size += numNew;
return numNew != 0;
}
5. 刪除元素
// 將指定位置的元素刪除
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index); // 獲取指定位置的元素
int numMoved = size - index - 1;
if (numMoved > 0) // 將指定位置後的元素左移一位
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null;
return oldValue;
}
// 刪除指定元素
public boolean remove(Object o) {
if (o == null) { // 找到指定元素的位置並將其刪除
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
// 刪除指定範圍的元素
protected void removeRange(int fromIndex, int toIndex) {
modCount++;
int numMoved = size - toIndex;
System.arraycopy(elementData, toIndex, elementData, fromIndex,
numMoved);
int newSize = size - (toIndex-fromIndex);
for (int i = newSize; i < size; i++) {
elementData[i] = null;
}
size = newSize;
}
// 刪除數組中與集合相等的元素
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c); // 檢查集合是否爲null
return batchRemove(c, false);
}
// 按指定條件刪除元素
@Override
public boolean removeIf(Predicate<? super E> filter) {
Objects.requireNonNull(filter);
int removeCount = 0; // 刪除元素的個數
final BitSet removeSet = new BitSet(size); // 記錄刪除元素的位置
final int expectedModCount = modCount;
final int size = this.size;
for (int i=0; modCount == expectedModCount && i < size; i++) {
@SuppressWarnings("unchecked")
final E element = (E) elementData[i];
if (filter.test(element)) { // 檢驗元素是否符合刪除條件
removeSet.set(i); // 將符合條件的元素在removeSet中對應的位置置true
removeCount++;
}
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
final boolean anyToRemove = removeCount > 0; // 是否有元素被刪除
if (anyToRemove) { // 若爲true則將數組中符合條件的元素刪除
final int newSize = size - removeCount;
for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) {
i = removeSet.nextClearBit(i);
elementData[j] = elementData[i];
}
for (int k=newSize; k < size; k++) {
elementData[k] = null;
}
this.size = newSize;
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
modCount++;
}
return anyToRemove;
}
// 刪除所有元素
public void clear() {
modCount++;
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
6. 修改元素
// 修改指定位置的元素,並返回舊值
public E set(int index, E element) {
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
7. 獲取元素
// 獲取指定位置的元素
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
E elementData(int index) {
return (E) elementData[index];
}
8. 擴容機制
// 當嘗試增加一個元素時,會調用該函數
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
// elementData:存儲元素的數組
// minCapacity:增加元素後數組的總大小
// 該方法用來計算並返回增加元素後數組的大小
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
// 決定是否擴容,
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// 若增加元素後數組大小大於原數組大小則需要擴容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
// 擴容至原數組大小的1.5倍
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // 上溢
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
- 計算增加元素後元素的個數:當增加元素時,會先調用方法計算增加元素後元素的個數,分爲兩種情況,若數組爲空則取初始化容量和增加元素後元素個數的最大值,否則直接返回增加元素後元素個數
- 判斷是否擴容:根據返回值,如果大於當前數組的容量則需要擴容
- 擴容:新的容量爲原來的1.5倍,若該值小於元素個數則新容量更改爲元素個數,若大於MAX_ARRAY_SIZE則取Integer允許的最大值和MAX_ARRAY_SIZE的最大值,若小於0即上溢,拋出異常
- 複製元素至擴容後的數組