在每一个覆盖了equals方法的类中,也必须覆盖hashcode方法。如果不这么做的话,就会违反Object.hashcode的通过约定,
从而导致该类无法结合所有基于散列的集合一起正常运作,这样的集合包括HashMap,HashSet和HashTable.
Object默认的hashCode是按地址所在的位置返回数据的,所以只要不是同一个对象,就会产生不同的结果,刚好和本身的equals方法吻合。
我们先做个测试,看看有什么问题:
public class PhoneNumber { private final short areaCode; private final short prefix; private final short lineNumber; public PhoneNumber(int areaCode,int prefix,int lineNumber){ rangeCheck(areaCode,999,"area code"); rangeCheck(prefix,999,"prefix"); rangeCheck(lineNumber,9999,"line number"); this.areaCode=(short)areaCode; this.prefix=(short)prefix; this.lineNumber=(short)lineNumber; } private static void rangeCheck(int arg,int max,String name){ if(arg<0||arg>max){ throw new IllegalArgumentException(name+":" +arg); } } @Override public boolean equals(Object o){ if(o==this) return true; if(!(o instanceof PhoneNumber)) return false; PhoneNumber pn=(PhoneNumber)o; return pn.getLineNumber()==lineNumber&&pn.getPrefix()==prefix&&pn.getAreaCode()==areaCode; } public short getPrefix() { return prefix; } public short getLineNumber() { return lineNumber; } public short getAreaCode() { return areaCode; } public String toString(){ return "["+areaCode+","+prefix+","+lineNumber+"]"; } }
测试:
public class Test { public static void main(String[] args){ Map<PhoneNumber,String> m=new HashMap<>(); m.put(new PhoneNumber(707,867,5309),"Jenny"); System.out.println(m.get(new PhoneNumber(707,867,5309))); } }我们理想的结果是返回Jenny,但是并不会,了解散列表的人就知道,散列表是依据散列码来存值的,不过散列码不相同,
就存在不同的桶中,当然就找不到了,所以,我们可以复写hashCode,来把我们认为相等的值返回相同的散列值,这样就
可以在hash表中找到我们想要的值。
private volatile int hashcode; @Override public int hashCode() { int result=hashcode; if(result==0){ result=17; result=31*result+areaCode; result=31*result+prefix; result=31*result+lineNumber; hashcode=result; } return hashcode; }再次测试:
Jenny