為什么重寫equals時要重寫hashCode

在每個覆蓋了equals方法的類中,都必須覆蓋hashCode方法。如果不這樣做的話,就會違反hashCode的通用約定,從而導(dǎo)致該類無法結(jié)合所有基于散列的集合一起正常運作,這類集合包括HashMap和HashSet。

Object規(guī)范預(yù)定:

如果兩個對象根據(jù)equals(Object)方法比較是相等的,那么調(diào)用這兩個對象中的hashCode方法都必須產(chǎn)生同樣的整數(shù)結(jié)果。

因沒有覆蓋 hashcode而違反的該關(guān)鍵約定:相等的對象必須具有相等的散列碼( hash code)。根據(jù)類的equals方法,兩個截然不同的實例在邏輯上有可能是相等的,但是根據(jù) Object類的 hashcode方法,它們僅僅是兩個沒有任何共同之處的對象。因此,對象的 hashcode方法返回兩個看起來是隨機的整數(shù),而不是根據(jù)第二個約定所要求的那樣,返回兩個相等的整數(shù)。

假設(shè)在 HashMap中用Phonenumber類的實例作為鍵:

Map<PhoneNumber, String> m = new HashMap<>();
m.put(new PhoneNumber(707, 867, 5309), "herohua");

此時,你可能期望m.get( new PhoneNumber(707,867,5309))會返回"herohua",但它實際上返回的是null。注意,這里涉及兩個 Phonenumber實例:第一個被插入 HashMap中,第二個實例與第一個相等,用于從Map中根據(jù) Phonenumber去獲取用戶名字。由于Phonenumber類沒有覆蓋 hashcode方法,從而導(dǎo)致兩個相等的實例具有不相等的散列碼,違反了 hashcode的約定。因此,put方法把電話號碼對象存放在一個散列桶(hash bucket)中,get方法卻在另一個散列桶中查找這個電話號碼。即使這兩個實例正好被放到同一個散列桶中,get方法也必定會返回null,因為 HashMap有一項優(yōu)化,可以將與每個項相關(guān)聯(lián)的散列碼緩存起來,如果散列碼不匹配,也就不再去檢驗對象的等同性。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容