在每個覆蓋了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方法返回兩個看起來是隨機(jī)的整數(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)的散列碼緩存起來暗赶,如果散列碼不匹配,也就不再去檢驗對象的等同性鄙币。