計算字串"code"的雜湊值
ascii值 a = 65 ---z = 90, a = 97 --- z = 122
c = 99 o = 111 d = 100 e =10199 * 31^3 + 111 * 31^2 + 100 * 31 ^1 + 101 = 3059181
// **計算同上列手算
string str = "code";
system.out.println(str.hashcode()); // 3059181
// c = 99, o = 111, d = 100, e = 101
system.out.println('c'*31*31*31 + 'o'*31*31 +'d'*31 + 'e'); // 3059181
為什麼是素數不是偶數
假若乘數為10,那麼以0結尾的整數,經過雜湊函式計算獲得的雜湊值可能會聚集在一起,產生衝突,還需要經過再雜湊或其他方法來解決衝突。
在解決衝突的過程中,探針會索引沒有利用的儲存空間,來儲存當前物件,因此降低了儲存效率
為什麼不可以是小一點的素數 2/3 呢
同樣是因為無法有效的進行雜湊,得到的hash值會聚集在一起
為什麼不可以是101甚至更大的素數 233
假如乘數因子是,使用上述雜湊函式計算有 99*101^3 = 101,999,799 只是計算四位字母的第乙個字母,hash值就已經達到一億了。
int整型的範圍為-2,147,483,648~2,147,483,647。如果是較長的字串,其計算結果會在整型範圍內溢位,最終會導致數值資訊丟失
因此只能選擇不大不小的乘數因子
故選擇 31, 33, 37, 39 和 41作為乘數,每個常數算出的雜湊值衝突數都非常小。
如果對超過 50,000 個英文單詞(由兩個不同版本的 unix 字典合併而成)進行 hash code 運算,並使用常數 31, 33, 37, 39 和 41 作為乘子,每個常數算出的雜湊值衝突數都小於7個
為什麼選擇31作為乘數因子
jvm裡最有效的計算方式就是進行位運算
而數字31有乙個很好的特性,即乘法運算可以被移位和減法運算取代,來獲取更好的效能
即31 * i == (i << 5) - i
左移 << :左邊的最高位丟棄,右邊補全0(把 << 左邊的資料*2的移動次冪)。
右移 >> :把》左邊的資料/2的移動次冪。
無符號右移 >>> :無論最高位是0還是1,左邊補齊0。
當 i = 2 時
左邊:31 x 2 = 62
右邊:(2 << 5) - 2 = 2 x 2 ^5 -2 = 62
jvm可以用此轉換方式進行高效運算
hashcode使用31作為乘法因子的原因小記
31是質子數中乙個 不大不小 的存在,如果你使用的是乙個如2的較小質數,那麼得出的乘積會在乙個很小的範圍,很容易造成雜湊值的衝突。而如果選擇乙個100以上的質數,得出的雜湊值會超出int的最大範圍,這兩種都不合適。而如果對超過 50,000 個英文單詞 由兩個不同版本的 unix 字典合併而成 進行...
a 為什麼不能作為左值
下面引用在部落格上看到的乙個易於理解的回答 首先說左值和右值的定義 變數和文字常量都有儲存區,並且有相關的型別。區別在於變數是可定址的 addressable 對於每乙個變數都有兩個值與其相聯 1 它的資料值,儲存在某個記憶體位址中。有時這個值也被稱為物件的右值 rvalue,讀做are value...
i 為什麼不能作為左值?
1 首先說左值和右值的定義 變數和文字常量都有儲存區,並且有相關的型別。區別在於變數是可定址的 addressable 對於每乙個變數都有兩個值與其相聯 1 它的資料值,儲存在某個記憶體位址中。有時這個值也被稱為物件的右值 rvalue,讀做are value 我們也可認為右值的意思是被讀取的值 r...