每一個重寫equals方法的類中,也必須重寫hashCode方法。java
若是不覆蓋hashCode,會致使沒法結合基於散列的集合正常工做,例如HashMap、HashSet和Hashtable等等,換句話說,實現了對的hashCode,就能夠拿對象的實例做爲Hash集合的Key,下面是重寫hashCode的規範:程序員
相等的對象必須具備相等的散列碼(hash code)。數組
兩個不一樣的實例在邏輯上有多是相等的(equals),可是hashCode方法返回的應該是兩個不一樣的隨機整數,考慮下面這個PhoneNumber類,在企圖與HashMap一塊兒使用時,將失敗:緩存
package test.ch02; public class PhoneNumber { private final int areaCode; private final int prefix; private final int lineNumber; public PhoneNumber(int areaCode, int prefix, int lineNumber) { this.areaCode = areaCode; this.prefix = prefix; this.lineNumber = lineNumber; } public int getAreaCode() { return areaCode; } public int getPrefix() { return prefix; } public int getLineNumber() { return lineNumber; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof PhoneNumber)) { return false; } PhoneNumber pn = (PhoneNumber) o; return pn.lineNumber == lineNumber && pn.prefix == prefix && pn.areaCode == areaCode; } }
package test.ch02; import java.util.HashMap; import java.util.Map; public class Test { public static void main(String[] args) { Map<PhoneNumber, String> m = new HashMap<>(); m.put(new PhoneNumber(707, 867, 5309), "Jenny"); String s = m.get(new PhoneNumber(707, 867, 5309)); System.out.println(s); // null } }
因爲PhoneNumber沒有重寫hashCode方法,從而致使兩個相等的實例具備不相等的散列碼。ide
修正這個問題很簡單,只須要爲PhoneNumber提供一個適當的hashCode便可。函數
一個好的hashCode方法傾向於「爲不相等的對象產生不相等的散列碼」。性能
理想狀況下,散列函數應該把集合中不相等的實例均勻地分佈到全部可能的散列值上,能夠採用以下作法:優化
爲PhoneNumber重寫一個hashCode:this
package test.ch02; public class PhoneNumber { private final int areaCode; private final int prefix; private final int lineNumber; public PhoneNumber(int areaCode, int prefix, int lineNumber) { this.areaCode = areaCode; this.prefix = prefix; this.lineNumber = lineNumber; } public int getAreaCode() { return areaCode; } public int getPrefix() { return prefix; } public int getLineNumber() { return lineNumber; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof PhoneNumber)) { return false; } PhoneNumber pn = (PhoneNumber) o; return pn.lineNumber == lineNumber && pn.prefix == prefix && pn.areaCode == areaCode; } @Override public int hashCode() { int result = 17; result = 31 * result + areaCode; result = 31 * result + prefix; result = 31 * result + lineNumber; return result; } }
package test.ch02; import java.util.HashMap; import java.util.Map; public class Test { public static void main(String[] args) { Map<PhoneNumber, String> m = new HashMap<>(); m.put(new PhoneNumber(707, 867, 5309), "Jenny"); String s = m.get(new PhoneNumber(707, 867, 5309)); System.out.println(s); // Jenny } }