HashMap原始碼解析

2021-08-28 04:12:28 字數 1502 閱讀 9513

以jdk1.8為例,hashmap是乙個用於儲存key-value鍵值對的集合,每乙個鍵值對是乙個node(jdk1.7叫做entry)。後台是用乙個node陣列來存放資料,這個node陣列就是hashmap的主幹。

這裡我們主要來分析hashmap的get和put方法。

public v put(k key, v value) 

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

boolean evict)

//這裡表示鍊錶中某個節點的key與即將插入的key相等,就跳出迴圈等待覆蓋

if (e.hash == hash &&

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

break;

p = e;}}

//這裡表示有節點的key與新的key相等,那麼就覆蓋

if (e != null)

} ++modcount;

//插入完之後,如果導致size超過了預設的閾值,就進行擴容(1.7是插入前判斷,1.8是插入後判斷)

if (++size > threshold)

resize();

afternodeinsertion(evict);

return null;

}

擴容步驟:

1、建立乙個原陣列兩倍大小的新陣列,並且把閾值擴大一倍。

2、遍歷原陣列,進行資料遷移。分為紅黑樹和鍊錶兩種情況。

好了,擴容部分就不展開**詳細說明,接下來進入get方法,相較於put方法就沒那麼複雜了,且**量也比較少

public v get(object key) 

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

}} return null;

}

注意:

1、hashmap底層就是用乙個個的node來儲存單個資料,每個node有hash值、key、value、及指向下乙個node的引用(next)。node陣列中就是所有鍊錶的頭節點。

2、當出現hash衝突的情況,原node的next就會指向新插入的node,也就是形成了鍊錶。

3、每次擴容的長度必須是2的冪,因為,根據key的hash值計算出的陣列索引應盡量不要重複,實現均勻分布,均勻分布的話大部分查詢的資料都是以陣列的形式查詢,就不會蛻變成煉表,而陣列的查詢效率比煉表高很多。

4、影響擴容的因素有兩個:陣列的長度(default_initial_capacity)和負載因子(default_load_factor),當這兩個相乘大於等於當前hashmap的size時,就進行擴容

5、擴容在併發情況下可能會形成鍊錶環,存在併發安全問題,這點需要注意

6、當鍊表的節點超過8個時,會轉成紅黑樹,鍊錶的時間複雜度為o(n),而紅黑樹為o(logn)

hashMap 原始碼解析

這幾天跳槽 被人問得最多的問題就是基礎方面的知識.當時學習的時候有點囫圇吞棗.現在回頭把這些基本的集合類原始碼都仔細閱讀下 hashmap 用的是最頻繁的.所以問得也最多了.initcapacity 初始化的容量 loadfacotr 負載因子 主要用來計算threshold的值 threshold...

HashMap原始碼解析

預設字段 static final int default initial capacity 1 4 預設node的陣列長度 16 static final int maximum capacity 1 30 陣列的最大長度 2 30 static final float default load ...

Hashmap原始碼解析

話不多說,直接看hashmap的put 方法原始碼 這是jdk1.8的原始碼 與1.7有所不同。final v putval int hash,k key,v value,boolean onlyifabsent,boolean evict if e.hash hash k e.key key ke...