Java 面試經典之 HashMap 原理

介紹

在你的工作面試中,這個問題被問了多少次?對我來說超過 10 次,我想把這個問題說得非常清楚,以節省每個人的時間。

HashMap 如何在 Java 中工作

HashMap 是一個基於散列表的鍵值對容器。它通常充當一個二進制哈希表,但是當 bins 變得太大時,它們就會被轉換成 TreeNodes 的 bins。

一個典型的 HashMap 看起來是這樣的:

Java 面試經典之 HashMap 原理

哈希表

該表充當索引,在第一次使用時初始化,例如 put(key, value)。默認容量為16。 假設我們初始化了一個 map:Map map = new HashMap<>(),我們現在想要 map.put(user1, "emai-add"),首先要識別表中的位置。Node 應該放在哪個單元格?

在哈希表中標識索引

Java 面試經典之 HashMap 原理

在 Java 1.8 的實現中,是通過 hashCode() 的高 16 位異或低 16 位實現的:(h = k.hashCode()) ^ (h >>> 16),主要是從速度、功效、質量來考慮的,這麼做可以在 bucket 的 n 比較小的時候,也能保證考慮到高低 bit 都參與到 hash 的計算中,同時不會有太大的開銷。

Java 面試經典之 HashMap 原理

節點

如果 table[index] 為空,我們可以直接 put 一個 Node(key, value) ,例如:

Java 面試經典之 HashMap 原理

如果單元格已經被佔用,檢查節點並更新/插入新節點:

Java 面試經典之 HashMap 原理

節點 Node 現在附加到哈希表上了。

在 put 方法的末尾,HashMap 將檢查是否需要 resize()。

必要時調整大小

當put時,如果發現目前的 bucket 佔用程度已經超過了 Load Factor 所希望的比例,那麼就會發生 resize。在 resize 的過程,簡單的說就是把 bucket 擴充為 2 倍,之後重新計算 index,把節點再放到新的 bucket 中。resize 的註釋是這樣描述的:

Initializes or doubles table size. If null, allocates in accord with initial capacity target held in field threshold. Otherwise, because we are using power-of-two expansion, the elements from each bin must either stay at same index, or move with a power of two offset in the new table.

大致意思就是說,當超過限制的時候會 resize,然而又因為我們使用的是 2 次冪的擴展(指長度擴為原來 2 倍),所以,元素的位置要麼是在原位置,要麼是在原位置再移動 2 次冪的位置。

Java 面試經典之 HashMap 原理

Java 面試經典之 HashMap 原理

如果超過了負載因子(默認0.75),則會重新 resize 一個原來長度兩倍的 HashMap,並且重新調用 hash 方法。

感謝大家的觀看,歡迎關注我的頭條號。


分享到:


相關文章: