為什么要先高16位異或低16位再取模運算


我們知道,n代表的是table的長度length,之前一再強調,表table的長度需要取2的整數次冪,就是為了這里等價這里進行取模運算時的方便——取模運算轉化成位運算公式:a%(2^n) 等價於 a&(2^n-1),而&操作比%操作具有更高的效率。
  當length=2n時,(length - 1)正好相當於一個"低位掩碼","與"操作的結果就是散列值的高位全部歸零,只保留低位,用來做數組下標訪問:

可以看到,當我們的length為16的時候,哈希碼(字符串“abcabcabcabcabc”的key對應的哈希碼)對(16-1)與操作,對於多個key生成的hashCode,只要哈希碼的后4位為0,不論不論高位怎么變化,最終的結果均為0。也就是說,如果支取后四位(低位)的話,這個時候產生"碰撞"的幾率就非常大(當然&運算中產生碰撞的原因很多,這里只是舉個例子)。為了解決低位與操作碰撞的問題,於是便有了第二步中高16位異或低16位的“擾動函數”。
右移16位,自己的高半區和低半區異或,就是為了混合原始哈希碼的高位和低位,以此來加大低位隨機性。

可以看到: 擾動函數優化前:1954974080 % 16 = 1954974080 & (16 - 1) = 0 擾動函數優化后:1955003654 % 16 = 1955003654 & (16 - 1) = 6 很顯然,減少了碰撞的幾率。


免責聲明!

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



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