20java hashmap原始碼解析(自己解析)

2021-09-05 10:04:49 字數 4805 閱讀 6443

public class hashmapextends abstractmapimplements map, cloneable, serializable
static final int default_initial_capacity = 1 << 4; // aka 16

static final int maximum_capacity = 1 << 30;

static final float default_load_factor = 0.75f;

static final int treeify_threshold = 8;

static final int untreeify_threshold = 6;

static final int min_treeify_capacity = 64;

static class nodeimplements map.entry

public final k getkey()

public final v getvalue()

public final string tostring()

public final int hashcode()

public final v setvalue(v newvalue)

public final boolean equals(object o)

return false;

}}

1 hash
static final int hash(object key)
通過key生成hash值。

2 comparableclassfor
static class<?> comparableclassfor(object x) }}

return null;

}

釋義

通過乙個物件來返回他的類

解析

3tablesizefor

static final int tablesizefor(int cap)
解析

給乙個值x,返回n 其中n的範圍為 2^(n-1) 4建構函式

public hashmap(int initialcapacity, float loadfactor) 

public hashmap(int initialcapacity)

public hashmap()

建構函式就是設定負載因子和初始化map大小。

5常用方法

5.1getnode()

public v get(object key) 

final nodegetnode(int hash, object key) while ((e = e.next) != null);}}

return null;

}

解析
總結

其實就是相當於乙個列車,有的車廂存的是鍊錶,有的車廂存的是樹,如果是樹,就呼叫樹的方法,如果是鍊錶就呼叫鍊錶的遍歷方法。

5.2containskey()

public boolean containskey(object key)
解析

直接調的get方法,判斷是否有這個key

5.3 put
public v put(k key, v value) 

final v putval(int hash, k key, v value, boolean onlyifabsent,

boolean evict)

if (e.hash == hash &&

((k = e.key) == key || (key != null && key.equals(k))))

break;

p = e;}}

v oldvalue = e.value;

if (!onlyifabsent || oldvalue == null)

e.value = value;

afternodeaccess(e);

return oldvalue;}}

++modcount;

if (++size > threshold)

resize();

afternodeinsertion(evict);

return null;

}/*擴容*/

final node resize()

else if ((newcap = oldcap << 1) < maximum_capacity &&

oldcap >= default_initial_capacity)

newthr = oldthr << 1; // double threshold

}else if (oldthr > 0) // initial capacity was placed in threshold

newcap = oldthr;

else

if (newthr == 0)

threshold = newthr;

@suppresswarnings()

node newtab = (node)new node[newcap];

table = newtab;

if (oldtab != null)

else

} while ((e = next) != null);

if (lotail != null)

if (hitail != null) }}

}}

return newtab;

}

解析:
注意:resize()擴容

當hashmap中的元素越來越多的時候,碰撞的機率也就越來越高(因為陣列的長度是固定的),所以為了提高查詢的效率,就要對hashmap的陣列進行擴容,陣列擴容這個操作也會出現在arraylist中,所以這是乙個通用的操作,很多人對它的效能表示過懷疑,不過想想我們的「均攤」原理,就釋然了,而在hashmap陣列擴容之後,最消耗效能的點就出現了:原陣列中的資料必須重新計算其在新陣列中的位置,並放進去,這就是resize。

那麼hashmap什麼時候進行擴容呢?當hashmap中的元素個數超過陣列大小loadfactor時,就會進行陣列擴容,loadfactor的預設值為0.75,也就是說,預設情況下,陣列大小為16,那麼當hashmap中元素個數超過160.75=12的時候,就把陣列的大小擴充套件為216=32,即擴大一倍,然後重新計算每個元素在陣列中的位置,而這是乙個非常消耗效能的操作,所以如果我們已經預知hashmap中元素的個數,那麼預設元素的個數能夠有效的提高hashmap的效能。比如說,我們有1000個元素new hashmap(1000), 但是理論上來講new hashmap(1024)更合適,不過上面annegu已經說過,即使是1000,hashmap也自動會將其設定為1024。 但是new hashmap(1024)還不是更合適的,因為0.751000 < 1000, 也就是說為了讓0.75 * size > 1000, 我們必須這樣new hashmap(2048)才最合適,既考慮了&的問題,也避免了resize的問題。

5.4 putall
public void putall(map<? extends k, ? extends v> m) 

final void putmapentries(map<? extends k, ? extends v> m, boolean evict)

else if (s > threshold)

resize();

for (map.entry<? extends k, ? extends v> e : m.entryset())

}}

解析
5.5 removenode
public v remove(object key) 

final noderemovenode(int hash, object key, object value,

boolean matchvalue, boolean movable)

p = e;

} while ((e = e.next) != null);}}

if (node != null && (!matchvalue || (v = node.value) == value ||

(value != null && value.equals(v))))

}return null;

}

解析
5.6 clear
public void clear() 

}

清除資料

5.7 containsvalue
public boolean containsvalue(object value) }}

return false;

}

AbstractCollection原始碼分析

abstractcollection抽象類提供了collection的骨架實現,collection分析請看 這裡直接看它的 是如何實現的.public abstract iterator iterator 該方法沒有實現.public abstract int size 該方法沒有實現.publi...

ThreadPoolExecutor原始碼閱讀

執行緒池解決兩個問題 一是復用執行緒,減少建立銷毀執行緒帶來系統開銷 二是限定系統資源使用邊界,避免大量執行緒消耗盡系統記憶體 適用於互不依賴,執行時間短,不需要對執行緒控制操作的執行緒 新增任務時,1.若執行緒數量小於corepoolsize,則新增執行緒執行任務 2.若執行緒數量大於等於core...

OrangePi One Android 原始碼編譯

一 系統環境搭建參照 二 lichee原始碼編譯 1.檢視help build.sh h2.配置核心 cd linux 3.4 make arch arm menuconfig 進入配置頁面,上下移動列表,空格是選擇列表,左右移動選擇退出選項 3.首次編譯執行清除 在 lichee linux3.4...