深究1 8版本HashMap原始碼

2022-07-06 01:24:10 字數 2191 閱讀 4714

public

v put(k key, v value)

在putval方法之前,對 key 進行了 hash 計算。

static

final

inthash(object key)

通過 hashcode() 方法和無符號左移16後的 hashcode 進行異或計算。 進行了一次擾動計算。

再看 putval 方法中。如何計算 key 再陣列中的下標。

1

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

onlyifabsent,

2boolean

evict)

23if (e.hash == hash &&

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

25break

;26 p =e;27}

28}29if (e != null) 36}

37 ++modcount;

38if (++size >threshold)

39resize();      // 擴容

40afternodeinsertion(evict);

41return

null

;42 }

在第 6 行中,   tab[i = (n - 1) & hash]  計算下標,使用了 hash 值跟 n-1 進行位與運算。

第一次初始容量為 16, hash 值跟 15 進行位 與運算。而 15 的二進位制是  1111。得到的是 hash 值的前 4位二進位制。所以得到的結果就是,0-15之間的數字,正好是陣列下標。

假如容量已經擴充套件,那現在的容量為  2n,hash 值跟 2n-1 進行位 與運算, 得到的是 hash 值的前 n 位二進位制。

原本的擴容方式就是將陣列變長,對每個節點資料重新計算下標,但是1.8版並不是這樣做的。看看原始碼:

1

final node resize()

11else

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

12 oldcap >=default_initial_capacity)

13 newthr = oldthr << 1; //

double threshold    // 否則,將原陣列大小擴充一倍14}

15else

if (oldthr > 0) //

initial capacity was placed in threshold

16 newcap =oldthr;

17else

21if (newthr == 0)

26 threshold =newthr;

27 @suppresswarnings()

28 node newtab = (node)new

node[newcap];

29 table =newtab;

30if (oldtab != null

) 52

else

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

);60

if (lotail != null

) 64

if (hitail != null

) 68}69

}70}71

}72return

newtab;

73 }

新版 hashmap 對擴容進行了優化,當容量擴充為原來的 2 倍時,只需判斷新增的一位 bit 是0還是1。

例如,當由 16 擴充至 32 時,16 的 二進位制時 10000,與 hash 計算,得到的是第 5 位 bit 的值。

原本計算下標,只是與前 4 位進行與運算,現在擴容一次後是對前 5 位進行與運算。

擴容方法裡面並沒有重新計算所有位的與運算,只需判斷新增的第 5 位。減少了計算量。

HashMap在JDK1 7和1 8版本的區別

在jdk1.7中hashmap是以entry陣列來儲存資料。用key的hashcode取模來決定key會被放在陣列裡的位置 如果hashcode相同,或者hashcode取模結果相同 那麼這些key會被定義到entry陣列的同乙個格仔裡,這些key會形成乙個鍊錶。1.在jdk1.8中hashmap是...

ubuntu18 04版本換源

1 備份cp etc apt sources.list etc apt sources.list.bak2 編輯原始檔vim etc apt sources.list3 更換原始檔 刪除sources.list檔案的內容,選擇以下的乙個源新增到sources.list檔案裡 vim的使用 1 esc...

基於 JDK1 7 版本實現 HashMap

在jdk1.7中是用的 陣列 單鏈表實現的hashmap 前一篇我用了linkedlist 陣列實現,其實本質上差不多,只是沒有寫擴容這一塊的內容,今天來個原生的方式實現hashmap。hashmap擴容機制?擴容後會產生什麼影響?因為很多解釋都寫到注釋裡面了,就不分模組解釋了。hashmap只允許...