前言
在Java中,每個對象都有一個從Object基類派生出的 hashCode() 方法,用於根據當前對象的某些特征返回一個整型變量。其核心源代碼(省略一些類型判斷與驗證代碼)如下所示:
public static int hashCode(byte[] value) { int h = 0; for (byte v : value) { h = 31 * h + (v & 0xff); } return h; }
那么為什么要這么計算,31這個數字是哪來的,本文將從理論和實踐層面進行詳細說明。
計算公式
為什么是數字31?
由於哈希碼(HashCode)的目的是為了區分對象,所以其分布自然是越均勻越好。為了保證分布均勻,一般的方法是使用一些相對大的素質,但是為什么選擇了31,而不是 23、29、37 或者直接更大的,如97?
在 《Effective Java》48頁,第 3 章 “Always override hashcode when you override equals” 寫道[2]:
A nice property of 31 is that the multiplication can be replaced by a shift and a subtraction for better performance: 31 * i == (i << 5) - i. Modern VMs do this sort of optimization automatically.
也就是說 31 * i
可以用 (i << 5) - i
來計算,而移位操作的效率高於乘法,所以這是基於性能角度的考慮。所以31即滿足素數的要求,又可以快速計算,所以被使用在對極致性能要求的Java源代碼中。
結論
通過源代碼,我們可以看到Java對性能有極致的追求,就hashCode的實現代碼中,做了兩大優化:
1)使用加乘運行代替連續階乘運算以提高效率;
2)使用可以用位左移操作計算的31代替其他運算。
轉載:https://blog.csdn.net/weixin_43145361/article/details/105904810