題目:【java源碼】ArrayList ArrayList 經常使用功能:構造函數、增、批量增、刪、批量刪、批量保留 ArrayList 屬性: // 默認數組長度(數組,而不是數據個數) private static final int DEFAULT_CAPACITY = 10; // 空數據 private static final Object[] EMPTY_ELEMENTDATA = {}; private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; // 實際用於存放數據的地方 transient Object[] elementData; // 數據個數 private int size; 1、構造函數 ①public ArrayList(); 只幹了一件事:this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; ②public ArrayList(int initialCapacity); 指定初始化elementData數組的初始大小。this.elementData = new Object[initialCapacity]; ③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; } } 2、增:就是數組中插一個元素操做思路 ①public boolean add(E e); 1、確保elementData數組可以裝下 首先判斷原來數組長度是否爲0,若是爲零,那麼新數組長度爲Math.max(DEFAULT_CAPACITY, 加入後數組最小應該長度); 判斷原來數組是否還裝的下,若是須要擴容那麼: private void grow(int minCapacity) { // 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); } 二、elementData[size++] = e;return true; ②public void add(int index, E element); 一、rangeCheckForAdd(index); // 檢測index是否越接 if (index > size || index < 0) 2、確保elementData數組可以裝下 三、System.arraycopy(elementData, index, elementData, index + 1, size - index); // 數組挪位 四、elementData[index] = element; 五、size++; 3、批量增:就是數組中插多個元素操做思路 ①public boolean addAll(Collection<? extends E> c); public boolean addAll(Collection<? extends E> c) { Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(size + numNew); // 同上:確保elementData數組可以裝下 System.arraycopy(a, 0, elementData, size, numNew); size += numNew; return numNew != 0; } ②public boolean addAll(int index, Collection<? extends E> c) public boolean addAll(int index, Collection<? extends E> c) { rangeCheckForAdd(index); Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(size + numNew); // // 同上:確保elementData數組可以裝下 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; } 4、刪:三點注意①按內容刪,只刪除第一個;②刪的是equals爲真的;③注意看fastRemove(index)源碼 ①public boolean remove(Object o); 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; } ②public E remove(int index); // 同理 ③private void fastRemove(int index); private void fastRemove(int index) { modCount++; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work } 5、批量刪、批量保留:一點注意:batchRemove方法。 ①public boolean removeAll(Collection<?> c); public boolean removeAll(Collection<?> c) { Objects.requireNonNull(c); return batchRemove(c, false); } ②public boolean retainAll(Collection<?> c); public boolean retainAll(Collection<?> c) { Objects.requireNonNull(c); return batchRemove(c, true); } ③private boolean batchRemove(Collection<?> c, boolean complement); // 思想:維護兩個指針。一個讀指針(r),一個寫指針(w)。讀指針從0遍歷到數組尾,在遍歷中,若是符合條件就elementData[w++] = elementData[r]; private boolean batchRemove(Collection<?> c, boolean complement) { final Object[] elementData = this.elementData; int r = 0, w = 0; boolean modified = false; try { for (; r < size; r++) if (c.contains(elementData[r]) == complement) elementData[w++] = elementData[r]; } finally { // Preserve behavioral compatibility with AbstractCollection, // even if c.contains() throws. if (r != size) { System.arraycopy(elementData, r, elementData, w, size - r); w += size - r; } if (w != size) { // clear to let GC do its work for (int i = w; i < size; i++) elementData[i] = null; modCount += size - w; size = w; modified = true; } } return modified; } 總結: 1、ArrayList經過內置一個Object數組實現順序表功能。經過grow函數實現動態增加,最大長度可在源碼中找答案。 二、刪除功能經過fastRemove函數實現對一個刪除,經過batchRemove函數實現對多個刪除。經過elementData[i] = null;或elementData[--size] = null; 的方式,讓JVM垃圾回收,自動回收。 private void grow(int minCapacity) { // 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); } private void fastRemove(int index) { modCount++; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work } private boolean batchRemove(Collection<?> c, boolean complement) { final Object[] elementData = this.elementData; int r = 0, w = 0; boolean modified = false; try { for (; r < size; r++) if (c.contains(elementData[r]) == complement) elementData[w++] = elementData[r]; } finally { // Preserve behavioral compatibility with AbstractCollection, // even if c.contains() throws. if (r != size) { System.arraycopy(elementData, r, elementData, w, size - r); w += size - r; } if (w != size) { // clear to let GC do its work for (int i = w; i < size; i++) elementData[i] = null; modCount += size - w; size = w; modified = true; } } return modified; }