深入理解Java之HashMap —— 02

生之智慧,在於摒棄不必要之事。若要最大限度成就真正重要之事,切忌貪多求全,事事應允。

1. HashMap的靈魂

HashMap的核心操作都是依靠着hash()展開的,在去看HashMap的操作之前,首先先了解一下hash()。

1.1 hash()

key的哈希值就是自身的hashCode的高16位和低16位進行異或運算得到的。

	static final int hash(Object key) {
        int h;
        // h >>> 16 右移16位,高位補0,取出高16位
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }
1.1.1 這樣設計的目的?

哈希表的容量被設計爲2的N次方,則當某個key的hashCode()值 > table.length,則高位就不會參與到hash的計算。通過hashCode的高16位異或低16位,這樣讓高位也能參與到hash的計算當中,從而降低hash衝突的風險。


2. HashMap的精髓

下面問題的重要性不言而喻…

2.1 key 爲null的hash值?

通過hash()方法,我們看到當key == null 時,其hash值爲0。從而保證了key爲null只能有一個

2.2 如何確定桶下標?

這裏需要我們注意的是:

HashMap中的桶下標是通過 (n-1)& hash 來計算的,而不是取模運算(hash%n)來計算。

2.3 確定桶下標爲什麼採用位運算而不是取模運算?

  1. 從運算時間上來講,位運算的效率遠遠好於取模運算

2.4 位運算如何保證下標不越界呢?

HashMap在設計上其容量必須是2的n次冪,用心良苦啊。
當 n 是 2的次冪時, n -1 的二進制表示法的尾部都是以連續1的形式來表示的。這樣當(n-1)與hash進行 與運算 時,會保留hash中後x 位的1,這樣就保證了索引值不會超過數組長度。

當 n 爲 2的方時,滿足:(n-1) & hash = hash % n

詳細內容請參看:Java HashMap爲什麼通過(n - 1) & hash 獲取哈希桶數組下標?


3. HashMap容量必須爲2的冪

簡而言之,還是基於效率上的考慮。即 位運算的運行效率要好於數學運算;

具體體現在:

  1. 數學運算從位運算實現。
  2. 參考2.4

這篇文章主要從HashMap的設計思路上來說明其設計之巧妙…

下一篇深入理解Java之HashMap —— 03從設計流程來探索HashMap.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章