本篇隨筆主要描述的是我閱讀 ArrayList 源碼期間的對於 ArrayList 的一些實現上的個人理解,有不對的地方,請指出~
先來看一下 ArrayList 的繼承圖:
由圖可以看出,ArrayList 的父類有 AbstractList、 AbstractCollection ,所以我從 AbstractCollection 類開始閱讀。
一、AbstractCollection 類相關。
AbstractCollection 類實現了 Collection 接口,並且由於 AbstractCollection 是一個抽象類,所以它只實現了一些 Collection 接口中的方法,例如 toArray() 方法, contains() 方法, remove() 方法等等。對於Collection 接口中含有的其它方法仍令其保持抽象實現,我認為這樣實現的原因是 :抽象類的作用就是一個概括作用,它需要將其子類中含有的公共方法在抽象類中加以實現,而抽象類中仍然保持抽象的方法一般都是每個子類有自己的實現,在抽象類中是沒有辦法統一起來的。
在 AbstractCollection 類中,我以為 finishToArray() 方法值得注意一下:
finishToArray() 方法是用來給數組 r[] 擴容的,每次當數組 r 的容量不足以容納迭代器遍歷到的元素時,就會對數組 r 進行擴容,並且對擴容後的數組容量進行校驗(hugeCapacity())。
擴容方法:newCap = cap + (cap >> 1)+ 1;
二、AbstractList 相關
AbstractList 也是一個抽象類,其下面具體的子類主要有 LinkedList, ArrayList, Vector幾種。所以 AbstractList 中含有的方法主要是對這幾個具體的子類的抽象。
我認為 AbstractList 中主要有以下幾點值得注意:
1、AbstractList 中 iterator() 和 listIterator() 均采用內部類方式實現。
1 public Iterator<E> iterator() { 2 return new Itr(); 3 } 4 5 public ListIterator<E> listIterator() { 6 return listIterator(0); 7 } 8 9 public ListIterator<E> listIterator(final int index) { 10 rangeCheckForAdd(index); 11 12 return new ListItr(index); 13 } 14 15 private class Itr implements Iterator<E> { 16 17 ...... 18 19 } 20 21 private class ListItr extends Itr implements ListIterator<E> { 22 ...... 23 }
2、AbstractList 中 removeRange() 方法為我們展示了如何運用迭代器移除 list 指定范圍的元素。
1 protected void removeRange(int fromIndex, int toIndex) { 2 ListIterator<E> it = listIterator(fromIndex); 3 for (int i=0, n=toIndex-fromIndex; i<n; i++) { 4 it.next(); 5 it.remove(); 6 } 7 }
3、並發修改異常 ConcurrentModificationException
在 AbstractList 中通過 expectedModCount 和 modCount 兩個量比較來判斷是否產生了並發修改異常,當迭代器在迭代過程中發現 expectedModCount 和 modCount 兩個量不相 等時就會拋出並發修改異常。modCount 代表改動 list 的次數,當獲得一個 iterator 或者 listIterator 時,就會將 modCount 值賦給 expectedModCount,在迭代器使用的過程中,如果出 現兩個值不相等的情況 ,就證明有迭代器之外的操作改動了 list,而這很可能會導致迭代器對 list 的操作出現錯誤,所以在接下來使用迭代器的時候就會拋出異常,這就是並發修改異 常的作用。
4、AbstractList 中的 subList() 方法。
先來看下 subList() 方法的實現:
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> { ...... public List<E> subList(int fromIndex, int toIndex) { return (this instanceof RandomAccess ? new RandomAccessSubList<>(this, fromIndex, toIndex) : new SubList<>(this, fromIndex, toIndex)); } ...... } class SubList<E> extends AbstractList<E> { SubList(AbstractList<E> list, int fromIndex, int toIndex) { l = list; offset = fromIndex; size = toIndex - fromIndex; this.modCount = l.modCount; } public E set(int index, E element) { return l.set(index+offset, element); } ...... } class RandomAccessSubList<E> extends SubList<E> implements RandomAccess { RandomAccessSubList(AbstractList<E> list, int fromIndex, int toIndex) { super(list, fromIndex, toIndex); } ...... }
可見有 SubList 與 RandomAccessSubList 兩種,區別在於是否實現 RandomAccess 接口 ,也就是是否可以隨機讀取,例如 ArrayList 可以隨機讀取,而 LinkedList 則只能順序讀 取。在SubList類的構造方法中,獲取了一個 AbstractList 類的引用,作用是利用這個引用實現 SubList 中的相關方法。
也就是說,subList 幾乎所有方法都是基於 AbstractList 類實現的,對於 subList 返回的 list 所做的所有改動都會反應到原來的 list 當中去。
三、ArrayList 相關