HashMap中hash(Object key)原理,為什么(hashcode >>> 16)。


大家都知道(jdk1.8)HashMap中計算數組下標是HashMap的核心算法。小編今天在看HashMap源碼中看到了hash(Object key)方法百思不得其解。小編問百度,查找相關博客,甚至連HashMap的關於hash(Object key)英文解釋都看了。但是都只是說了為了盡量均勻,沒有詳細講。小編今天為大家詳細講解一下這兩個問題。

HashMap中hash(Object key)的原理,為什么這樣做?
先看下hash(Object key)方法,詳細大家基本都能看懂,但是知道這一步(h = key.hashCode()) ^ (h >>> 16)原因的人很少。

static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
首先這個方法的返回值還是一個哈希值。為什么不直接返回key.hashCode()呢?還要與 (h >>> 16)異或。首先要了解以下知識點:

必備知識點.:^ 運算  >>>運算  &運算。

1. h >>> 16 是什么,有什么用?
h是hashcode。h >>> 16是用來取出h的高16,(>>>是無符號右移)   如下展示:

0000 0100 1011 0011 1101 1111 1110 0001

>>> 16

0000 0000 0000 0000 0000 0100 1011 0011
2. 為什么 h = key.hashCode()) 與 (h >>> 16) 異或
講到這里還要看一個方法indexFor,在jdk1.7中有indexFor(int h, int length)方法。jdk1.8里沒有,但原理沒變。下面看下1.7源碼

1.8中用tab[(n - 1) & hash]代替但原理一樣。

static int indexFor(int h, int length) {
return h & (length-1);
}
這個方法返回值就是數組下標。我們平時用map大多數情況下map里面的數據不是很多。這里與(length-1)相&,

但由於絕大多數情況下length一般都小於2^16即小於65536。所以return h & (length-1);結果始終是h的低16位與(length-1)進行&運算。如下例子(hashcode為四字節)

例如1:為了方便驗證,假設length為8。HashMap的默認初始容量為16

length = 8;  (length-1) = 7;轉換二進制為111;

假設一個key的 hashcode = 78897121 轉換二進制:100101100111101111111100001,與(length-1)& 運算如下
   

0000 0100 1011 0011 1101 1111 1110 0001

&運算

0000 0000 0000 0000 0000 0000 0000 0111

= 0000 0000 0000 0000 0000 0000 0000 0001 (就是十進制1,所以下標為1)
上述運算實質是:001 與 111 & 運算。也就是哈希值的低三位與length與運算。如果讓哈希值的低三位更加隨機,那么&結果就更加隨機,如何讓哈希值的低三位更加隨機,那么就是讓其與高位異或。

補充知識:

當length=8時    下標運算結果取決於哈希值的低三位

當length=16時  下標運算結果取決於哈希值的低四位

當length=32時  下標運算結果取決於哈希值的低五位

當length=2的N次方, 下標運算結果取決於哈希值的低N位。

3. 原因總結
由於和(length-1)運算,length 絕大多數情況小於2的16次方。所以始終是hashcode 的低16位(甚至更低)參與運算。要是高16位也參與運算,會讓得到的下標更加散列。

所以這樣高16位是用不到的,如何讓高16也參與運算呢。所以才有hash(Object key)方法。讓他的hashCode()和自己的高16位^運算。所以(h >>> 16)得到他的高16位與hashCode()進行^運算。

4. 為什么用^而不用&和|
因為&和|都會使得結果偏向0或者1 ,並不是均勻的概念,所以用^。

這就是為什么有hash(Object key)的原因。


————————————————
版權聲明:本文為CSDN博主「楊濤的博客」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_42034205/article/details/90384772


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM