每一个重写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 } }