題目:【java原始碼】ArrayList ArrayList 常用功能:建構式、增、批量增、刪、批量刪、批量保留 ArrayList 屬性: // 默認陣列長度(陣列,而不是資料個數) private static final int DEFAULT_CAPACITY = 10; // 空資料 private static final Object[] EMPTY_ELEMENTDATA =https://www.cnblogs.com/Twobox/p/ {}; private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA =https://www.cnblogs.com/Twobox/p/ {}; // 實際用于存放資料的地方 transient Object[] elementData; // 資料個數 private int size; 1、建構式 ①public ArrayList(); 只干了一件事:this.elementData =https://www.cnblogs.com/Twobox/p/ DEFAULTCAPACITY_EMPTY_ELEMENTDATA; ②public ArrayList(int initialCapacity); 指定初始化elementData陣列的初始大小,this.elementData = https://www.cnblogs.com/Twobox/p/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 =https://www.cnblogs.com/Twobox/p/ 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 =https://www.cnblogs.com/Twobox/p/ Arrays.copyOf(elementData, newCapacity); } 2、elementData[size++] = e;return true; ②public void add(int index, E element); 1、rangeCheckForAdd(index); // 檢測index是否越接 if (index > size || index < 0) 2、確保elementData陣列能夠裝下 3、System.arraycopy(elementData, index, elementData, index + 1, size - index); // 陣列挪位 4、elementData[index] = element; 5、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 = https://www.cnblogs.com/Twobox/p/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函式實作動態增長,最大長度可在原始碼中找答案, 2、洗掉功能通過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 =https://www.cnblogs.com/Twobox/p/ 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 = https://www.cnblogs.com/Twobox/p/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; }
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/233781.html
標籤:Java
下一篇:PHP設計模式之抽象工廠模式
