源碼還是比較多的,安安靜靜的讀完確實不易,所以我們讀源碼要有著重點。
1 繼承和實現
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {}
聲明任何方法的,沒有方法並不代表沒有用,他們分別表示ArrayList具有可隨機訪問,可克隆及可序列化能力。
/** * 靜態常量 空數組 用於返回 元素為空的實例 */ private static final Object[] EMPTY_ELEMENTDATA = {};
/** * 空數組 和 EMPTY_ELEMENTDATA 用於區別,以便在第一個元素添加時知道擴容多少 */ private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//用來記錄集合結構變動的次數 protected transient int modCount = 0;
/** * 靜態常量 默認容量 */ private static final int DEFAULT_CAPACITY = 10;
/** * 包含元素的數量,私有變數只能通過size()方法獲得 */ private int size;
/** * 數組的最大長度,一些虛擬機在存儲數組對象時會將一些頭信息存入其中, * 分配過大的數組空間很可能導致 OOM,數組長度超過VM的限制。 */ private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/** * 聲明一個默認許可權的數組,用以存儲元素,只能在本類或本包中訪問 */ transient Object[] elementData;
ArrayList的一個子集視圖,為什麼說是視圖呢?因為它展示的就是ArrayList中的部分元素,無論改變它本身還是ArrayList,雙方都會手影響。
迭代器Iterator介面的實現類。
繼承於Itr,是Itr的功能增強版。
分割迭代器,可以將迭代器分割一分為二,依次類推。
new ArrayList()
new ArrayList(10)
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() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
public ArrayList() { //這裡調用第一個指定容量的構造方法,傳入了10作為初始容量 this(10); }
public ArrayList(Collection<? extends E> c) { //調用集合的toArray()方法將集合轉為數組 elementData = c.toArray(); if ((size = elementData.length) != 0) {
if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // replace with empty array. this.elementData = EMPTY_ELEMENTDATA; } }
toArray()
elementData
public boolean add(E e) { //判斷是否擴容 ensureCapacityInternal(size + 1); elementData[size++] = e; return true; } private void ensureCapacityInternal(int minCapacity) { //如果當前集合中元素為空,那麼 選取 默認容量和最小容量 中的最大值 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); }
ensureExplicitCapacity(minCapacity); } private void ensureExplicitCapacity(int minCapacity) { modCount++;
// 擴容時機:當容量全部被佔用完時,那麼進行擴容 if (minCapacity - elementData.length > 0) grow(minCapacity); }
private void grow(int minCapacity) { int oldCapacity = elementData.length;
//新容量為原來的1.5倍 int newCapacity = oldCapacity + (oldCapacity >> 1);
//如果擴容1.5倍後還不滿足需要的最小容量 // 那麼就直接擴容到所需的最小容量 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; //複製原來數組元素到一個新長度的數組中 elementData = Arrays.copyOf(elementData, newCapacity); }
oldCapacity >> 1
List<String> list = new ArrayList<>(Arrays.asList("code","code","test","hello"));
for(inti=0;i<list.size();i++){ String a=list.get(i); if (a.equals("code")) { list.remove(a); } }
錯誤二
for (String s: list) { if (s.equals("code")){ list.remove(s); } }
ConcurrentModificationException
錯誤三
list.forEach(s -> { list.remove(s); });
remove
分析
int expectedModCount = modCount; //省略步驟 if (modCount != expectedModCount) throw new ConcurrentModificationException();
正確方式
Iterator<Integer> iterator = list.iterator(); while (iterator.hasNext()){ Integer next = iterator.next(); iterator.remove(); }
iterator.remove()
源碼閱讀 在GItHub上:
flyhero/JDK8-Note?github.com
1. 千萬不要這樣使用 Arrays.asList !