JAVA中的集合原始碼分析一:ArrayList的內部實現原理
阿新 • • 發佈:2018-12-21
作為以java為語言開發的android開發者,集合幾乎天天都要打交道,無論是使用頻率最高的ArrayList還是HashSet,都頻繁的出現在平時的工作中。但是其中的原理之前卻一直沒深入探究,接下來記錄一下這次自己學習ArrayList原始碼的過程。
一.構造方法:
private static final int DEFAULT_CAPACITY = 10;//預設陣列長度 transient Object[] elementData; //空陣列 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //預設空陣列 private static final Object[] EMPTY_ELEMENTDATA = {}; //空陣列 /** *建立一個空陣列 */ public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } /** *建立一個長度為輸入長度initialCapacity的一個數組 */ 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); } }
首先看構造方法,其實構造方法很簡單,就是建立一個數組。顧名思義,arraylist底層其實就是以陣列進行實現的,普通的構造方法List list = new ArrayList();實現的就是建立一個空陣列。而帶引數的構造方法則是建立一個長度為輸入長度的陣列。
二.add方法:
//新增一個子項 public boolean add(E e) { ensureCapacityInternal(size + 1); // 對陣列進行擴容判斷 elementData[size++] = e; return true; } private void ensureCapacityInternal(int minCapacity) { ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));//計算現在的陣列和需要擴容的大小進行比較 } private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0)//如果需要擴容到的大小大與當前陣列的容量,對其進行擴容 grow(minCapacity); } private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; //當前容量 int newCapacity = oldCapacity + (oldCapacity >> 1); //新容量,對其進行移位計算 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); //經過激烈的大小比較,獲取到一個新陣列 }
add運算需要對當前的陣列容量進行比較,如果大於當前容量,需要通過移位運算進行擴容,隨後再把原先的陣列複製到新陣列中,最後再新增新元素。
三.remove方法:
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; } private void fastRemove(int index) { modCount++; int numMoved = size - index - 1; //獲取到需要刪除的陣列下標 if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved);//將刪除位置後面的元素集體複製到需要刪除的位置,也就是說將numMoved後面的所有元素整體前移一位。 elementData[--size] = null; // clear to let GC do its work }
remove方法是比較方便理解的,就是通過for迴圈找到需要刪除的位置,然後再通過陣列的前移來將需要刪除的元素移除,表面上是刪除了某個元素,實際上是將它後面的所有元素往前移動了一位,最後將size減一,並且置空最後一個元素。
四.clear方法
public void clear() {
modCount++;
// clear to let GC do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
這個沒什麼好說的,也就是通過for迴圈將陣列中每個元素置空。