JDK之ArrayList原始碼解讀 一

2021-09-07 10:37:17 字數 3696 閱讀 8044

原始碼基於jdb_1.8版本。

目錄

建構函式1

建構函式2

建構函式3

contains(object o)

lastindexof(object o)

toarray()

get(int index)

set(int index, e element)

add(e e)

add(int index, e element)

clone()

public arraylist(int initialcapacity)  else if (initialcapacity == 0)  else 

}

可以看出,arraylist本質上就是乙個陣列,資料型別是object。當傳入的引數大於0時,建立乙個大小為初始值的陣列;如果引數等於0,則建立乙個空陣列

private static final object empty_elementdata = {};
其他情況下,丟擲異常。

public arraylist()
不傳參時,也同樣建立乙個空陣列

private static final object defaultcapacity_empty_elementdata = {};
public arraylist(collection<? extends e> c)  else 

}

通過另乙個collection來初始化arraylist。當這個collection的型別也是陣列型別時,直接通過=來賦值。如果不是,則通過arrays.copyof的方法來賦值。

public boolean contains(object o)
檢測arraylist是否包含某個物件,通過索引該物件在arraylist中的位置來判斷是否包含。如果位置》=零,說明物件在arraylist中。其中indexof(object o)如下:

public int indexof(object o)  else 

return -1;

}

當該物件為null時,遍歷arraylist,遇到第乙個值為null的位置時,返回該位置的索引;

當該物件不為null時,遍歷arraylist,遇到第乙個值與該物件相等的位置時,返回該位置的索引。

當遍歷完所有位置都未找到相等的位置時,返回-1。

public int lastindexof(object o)  else 

return -1;

}

返回物件在arraylist中的最後乙個位置。該方法和indexof(object o)的方法基本一樣,只不過遍歷的時候是從arraylist的末尾處往前遍歷。

public object toarray()
arraylist轉換成位元組陣列,直接呼叫arrays.copyof方法。

public e get(int index)
該方法獲取arraylist指定位置的值,呼叫了rangecheck(index)和elementdata(index)。

private void rangecheck(int index)
該方法校驗index的值是否超過arraylist,超過就丟擲陣列越界錯誤。

@suppresswarnings("unchecked")

e elementdata(int index)

該方法直接返回陣列在指定位置的值,因為arraylist本質上就是陣列。

public e set(int index, e element)
先檢查傳入的索引引數是否越界。再獲取arraylist中原來在這個位置上的值oldvalue,然後再將這個位置上的值替換成新的值,返回舊值oldvalue。

public boolean add(e e)
先呼叫ensurecapacityinternal,然後將陣列的最大位置的下一位設定成傳入的值,返回true表示插入成功。

private void ensurecapacityinternal(int mincapacity) 

ensureexplicitcapacity(mincapacity);

}private void ensureexplicitcapacity(int mincapacity)

該方法的作用是確認組成arraylist裡的元素個數是否超過陣列的容量。如果陣列是空陣列,則mincapacity取default_capacity和傳入的引數中比較大的那個值。例如new arraylist(2),而陣列預設的初始值是10,則mincapacity賦值為10。如果mincapacity大於陣列的長度,這個時候需要將陣列擴容,因為陣列的大小是不可變的,因此需要重新建立乙個陣列,將原陣列的內容賦值過去。擴容方法是grow(mincapacity)。modcount記錄集合的修改次數,也就每次add或者remove它的值都會加1。 

private void grow(int mincapacity)
每次按照原陣列50%的大小進行擴容。如果增大50%後的陣列大小依然小於傳入的引數mincapacity的話,則就將該引數mincapacity作為新陣列的大小(一般不會發生)。如果新陣列的大小超過了integer.max_value - 8,呼叫hugecapacity

private static int hugecapacity(int mincapacity)
如果mincapacity超過了integer.max_value就會變成負數,此時丟擲記憶體溢位;

否則,integer.max_value - 8  < mincapacity < integer.max_value,這個時候,建立乙個integer.max_value長度的陣列。

然後通過arrays.copyof建立乙個新陣列,將原陣列複製過去。

public void add(int index, e element)
作用:在指定位置插入元素。

首先通過rangecheckforadd檢查位置索引是否合法

private void rangecheckforadd(int index)
如果位置索引大於arraylist的元素個數或者小於0,丟擲陣列越界異常。

再通過ensurecapacityinternal檢查陣列是否已滿、是否需要擴容(前面add方法已介紹過)。

然後呼叫system.arraycopy方法,這是乙個native方法,作用是:將陣列中index處往後的所有元素都往後面移動乙個位置,一共需要移動size - index個元素。然後再將新元素放在陣列中index的位置上,同時arraylist的元素個數加1。

public object clone()  catch (clonenotsupportedexception e) 

}

通過arrays.copyof建立乙個大小一樣的新陣列,將原陣列複製過去,同時將modcount重置為0。

JDK1 8 ArrayList擴容機制原始碼分析

屬性 預設長度 private static final int default capacity 10 空陣列 有參構造器 private static final object empty elementdata 空陣列 無參構造器 private static final object def...

ArrayList的remove 方法原始碼解讀

remove index public boolean remove object obj else return false arraylist的remove object obj 方法判斷是否為同乙個物件的時候用的是equals方法,如果我們要移除list中的自定義類的時候需要重寫equals方...

JDK13 HashMap resize原始碼解析

resize是重新雜湊,所以要在現在容量和閾值的基礎上獲取新的容量和閾值,函式首先進行了變數定義 final hashmap.node resize else if newcap oldcap 1 maximum capacity oldcap default initial capacity de...