基礎 | 重寫hashCode方法
參加美團秋招面試時,被問到 「如何重寫hashCode方法?重寫hashCode()方法需要注意什麼?」,在此做一個系統的總結與梳理,同時也填一下之前埋下的坑,哈哈。
參考答案
為什麼要重寫hashCode()方法?
Object類中hashCode()方法預設是將物件的儲存地址進行對映,並返回一個整形值作為雜湊碼。
若重寫equals()方法,使其比較兩個物件的內容,並保留hashCode()方法的預設實現,那麼兩個明明「相等」的物件,雜湊值卻可能不同。
如果兩個物件通過equals()方法比較的結果為true,那麼要保證這兩個物件的雜湊值相等。
因此,在重寫equals()方法時,建議一定要重寫hashCode()方法。
如何重寫hashCode()方法?
由於Object類的 hashCode() 方法是本地的(native),故其具體實現並不是由Java所完成的。
需要實現hashCode()方法時,可以直接呼叫Objects.hash(Object… values)方法來獲取對應的雜湊值。其內部的具體實現是呼叫Arrays.hashCode(Object[])方法來完成的。
Arrays中計算雜湊值的核心程式碼如下:
public static int hashCode(Object a[]) {
if (a == null)
return 0;
int result = 1;
for (Object element : a)
result = 31 * result + (element == null ? 0 : element.hashCode());
return result;
}
The value 31 was chosen because it is an odd prime. If it were even and the multiplication overflowed, information would be lost, as multiplication by 2 is equivalent to shifting. The advantage of using a prime is less clear, but it is traditional. 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. ------引用自《Effective Java》
重寫hashCode()方法需要注意什麼?
- 應用程式執行期間,只要一個物件用於equals()方法的屬性未被修改,則該物件多次返回的雜湊值應相等。
- 如果兩個物件通過equals()方法比較的結果為true,那麼要保證這兩個物件的雜湊值相等。
- 如果兩個物件通過equals()方法比較的結果為false,那麼這兩個物件的雜湊值可以相等也可以不相等,但理想情況下是應該不相等,以提高散列表的效能。
原始碼閱讀
// Object類中hashCode()方法的預設實現
public native int hashCode();
// Arrays中計算雜湊值的核心程式碼
public static int hashCode(Object a[]) {
if (a == null)
return 0;
int result = 1;
for (Object element : a)
result = 31 * result + (element == null ? 0 : element.hashCode());
return result;
}
推薦閱讀
歡迎關注
Java名企面試吧,每天10點24分,我們不見不散!
丙子先生的宗旨是,每天以短篇幅講高頻面試題,不增加太多負擔,但需要持之以恆。
能力有限,歡迎指教!