JDK1 8原始碼閱讀系列之一 ArrayList

2022-07-27 03:45:12 字數 3771 閱讀 8588

本篇隨筆主要描述的是我閱讀 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 iteratoriterator() 45

public listiteratorlistiterator() 89

public listiteratorlistiterator(final

intindex)

1415

private

class itr implements iterator

2021

private

class listitr extends itr implements listiterator

2、abstractlist 中 removerange() 方法為我們展示了如何運用迭代器移除 list 指定範圍的元素。(相比於 arraylist 中的 removerange 方法,用迭代器實現的 removerange 複雜度                   較高)

1

protected

void removerange(int fromindex, int

toindex)

7 }

3、併發修改異常 concurrentmodificationexception

在 abstractlist 中通過 expectedmodcount 和 modcount 兩個量比較來判斷是否產生了併發修改異常,當迭代器在迭代過程中發現 expectedmodcount 和 modcount 兩個量不相                 等時就會丟擲併發修改異常。modcount 代表改動 list 的次數,當獲得乙個 iterator 或者 listiterator 時,就會將 modcount 值賦給 expectedmodcount,在迭代器使用的過程中,如果出                 現兩個值不相等的情況 ,就證明有迭代器之外的操作改動了 list,而這很可能會導致迭代器對 list 的操作出現錯誤,所以在接下來使用迭代器的時候就會丟擲異常,這就是併發修改異                 常的作用。

4、abstractlist 中的 sublist() 方法。

先來看下 sublist() 方法的實現:

public

abstract

class abstractlistextends abstractcollectionimplements list

......

}class sublistextends abstractlist

public e set(int

index, e element)

......

}class randomaccesssublistextends sublistimplements

randomaccess

......

}

可見有 sublist 與 randomaccesssublist 兩種,區別在於是否實現 randomaccess 介面 ,也就是是否可以隨機讀取,例如 arraylist 可以隨機讀取,而 linkedlist 則只能順序讀                 取。在sublist類的構造方法中,獲取了乙個 abstractlist 類的引用,作用是利用這個引用實現 sublist 中的相關方法。

也就是說,sublist 幾乎所有方法都是基於 abstractlist 類實現的,對於 sublist  返回的 list 所做的所有改動都會反應到原來的 list 當中去。

三、arraylist 相關

我認為 arraylist 原始碼中以下幾點值得注意:

1、在 arraylist 把集合當做構造器中引數涉及到的 jdk bug,原始碼如下:

1

public arraylist(collection extends e>c)

在原始碼中可以看到由於  c.toarray might (incorrectly) not return object ,所以運用反射進行了 class 型別的判斷,那麼什麼時候會出現這種情況呢?下面舉例

說明:

1

public

static

void

main(string args)

輸出結果為:

可以看到 list 與 list1 的 toarray 方法返回的陣列型別是不相同的,如果嘗試向 string 型別陣列中插入其它型別元素,就會丟擲異常。所以

public arraylist(collection extends e> c) {} 方法中要對 collection.toarray() 方法返回的陣列型別進行判斷,如果不是 object,就要新建乙個 object,並進行複製。

2、arraylist 擴容方法

1

private

void grow(int

mincapacity)

採用 oldcapacity + (oldcapacity >> 1)來擴充容量。

3、與 abstractlist 相似,arraylist 的 sublist 方法也是基於 arraylist 實現的,對於 sublist 產生的 list 的所有操作都會反映到原來的 arraylist 上。

arraylist 原始碼相關就介紹到這裡。

JDK1 8原始碼閱讀(五) ArrayList

顧名思義,arraylist的結構實際就是乙個陣列。所以它的特性很明顯,插入乙個元素的時候,是耗時是乙個常量時間o 1 在插入n個元素的時候,需要的時間就是o n arraylist類圖設計 初始化預設容量 private static final int default capacity 10 空...

JDK1 8 二 Thread 原始碼閱讀筆記

這裡有的未知的就不貼出來了 private volatile char name 執行緒名稱 private int priority 執行緒優先順序 private boolean single step 是否單步執行 private boolean stillborn false 虛擬機器狀態 ...

Vector原始碼解析 jdk1 8

概述 vector實現了list的介面,底層同樣是基於陣列實現的,可以儲存null。功能結構與arraylist的類似,不同的是執行緒安全的。建構函式protected object elementdata protected int capacityincrement public vector ...