分析過Immutable Collections後,進入具體的數據結構來分析,這一次咱們來看看ImmutableList。做爲線性可重複集合,ImmutableList的底層實現採用了數組,由於不可變集合,就不存插入刪除的操做。數組的下標使得根據index的read的操做,時間複雜度變爲了O(1)。對於ImmutableList的兩種實現,咱們先來看下UML圖。數組
首先,咱們看下構造一個ImmutableList的方法數據結構
@Test public void constructImmutableList() { ImmutableList<Integer> list1 = ImmutableList.of(1, 2, 3, 4); ImmutableList<Integer> list2 = ImmutableList.copyOf(Lists.newArrayList(1, 2, 3, 4)); }
首先of()方法被重載了12次(後文會詳細介紹緣由),of()方法的實現,根據參數個數的不一樣,採用了不一樣的實現,1個參數爲ide
public static <E> ImmutableList<E> of(E element) { return new SingletonImmutableList<E>(element); }
根據SingletonImmutableList的內部實現能夠看出,對於一個元素的ImmutableList,Guava並無在內部維護一個數組,而是維護了一個元素,而其餘的操做都會針對,單個元素進行了優化,例如contains()方法的實現變爲了equals的比較。具體代碼以下:優化
final class SingletonImmutableList<E> extends ImmutableList<E> { final transient E element; @Override public boolean contains(@Nullable Object object) { return element.equals(object); } }
多個參數的of()方法實現,都會依賴於construct()方法this
private static <E> ImmutableList<E> construct(Object... elements) { return asImmutableList(checkElementsNotNull(elements)); }
而construct()方法最終依賴於asImmutableList()方法實現,代碼以下:spa
static <E> ImmutableList<E> asImmutableList(Object[] elements, int length) { switch (length) { case 0: return of();//直接返回空數組 case 1: @SuppressWarnings("unchecked") // collection had only Es in it ImmutableList<E> list = new SingletonImmutableList<E>((E) elements[0]);//返回SingletonImmutableList,上面分析過 return list; default: if (length < elements.length) {//of方法的length和elements.length都是相等的 elements = arraysCopyOf(elements, length); } return new RegularImmutableList<E>(elements); } }
RegularImmutableList內部維護Object數組,對於集合接口的實現,所有依賴於對數組下標和偏移量的實現設計
class RegularImmutableList<E> extends ImmutableList<E> { private final transient int offset; private final transient int size; private final transient Object[] array; RegularImmutableList(Object[] array, int offset, int size) { this.offset = offset; this.size = size; this.array = array; } RegularImmutableList(Object[] array) { this(array, 0, array.length); } @Override @SuppressWarnings("unchecked") public E get(int index) { Preconditions.checkElementIndex(index, size); return (E) array[index + offset];//對於集合的操做,所有轉換爲對數據的index和offset的操做,時間複雜度變爲O(1) } }
其中有一個方法實現的很是巧妙,subListUnchecked()方法,實現並無構造新的Object[]數組,而是在利用原有的數組,但偏移量有所改變。全部的寫操做都已經被屏蔽,因此Object[]數組成爲了避免可變,截取操做只是變成了對原有Object[]上下界的操做。節省了不少空間code
ImmutableList<E> subListUnchecked(int fromIndex, int toIndex) { return new RegularImmutableList<E>( array, offset + fromIndex, toIndex - fromIndex); }
仔細的童鞋能夠發現,ImmutableList的of()方法,被重載了12次,爲何Guava的設計者不適用可變參數列表呢?緣由在於,改進使用帶泛型可變參數的方法時的編譯器警告和錯誤提示,若是在泛型與可變參數列表同時適用會產生編譯警告和堆污染,Guava本身重載了11次of方法,根據不一樣的參數個數,並且建議你of方法一次性傳11個參數就能夠了(良好的代碼書寫,告訴咱們不要這樣作)。htm
另外一個須要分析的就是ImmutableList的copyOf方法,若是copyOf的傳參是一個ImmutableCollection(非部分視圖),其實並無真正的進行了copy操做,若是是非ImmutableCollection,那麼,就會進行真正的copy。blog
public static <E> ImmutableList<E> copyOf(Collection<? extends E> elements) { if (elements instanceof ImmutableCollection) { @SuppressWarnings("unchecked") // all supported methods are covariant ImmutableList<E> list = ((ImmutableCollection<E>) elements).asList(); return list.isPartialView() ? ImmutableList.<E>asImmutableList(list.toArray())//isPartialView==true,進行copy : list;//直接返回,由於不可變 } return construct(elements.toArray());//進行copy }