从刚接触java时候在面试时就时常遇到面试官问这样的问题:equals相等那么hashcode相等吗?也一直没有怀疑过这个逻辑的正确性。直道上个月,公司一个技术主管居然说:equals相等hashcode不一定相等! 这是语出惊人!我当时强烈反驳,拿出最典型的例子String,Integer等对象说明自己观点的正确性。同样这位主管也拿出了自己代码做了论证,看了看代码,最后打印的结果还真是equals比较相等,hashcode值不同。
首先我们说hashcode是个伟大的发明,这条真理也极大减化在开发过程中对象比较,用处不可谓不广。如果这条真理违背了,也就失去hash意义。为什么这位主管大人会在代码中论证了他的论点呢?最后花时间回来研究了一下,发现他在使用对象代码中只实现了equals方法,而没有重写hashcode方法,这就是问题根源所在。空说无凭,举例来说吧:
package org.hash;
import java.util.HashMap;
import java.util.Map;
public final class PhoneNumber {
private final short areaCode;
private final short exchange;
private final short extension;
private volatile int hashCode=0;
public PhoneNumber(int areaCode,int exchange,int extension){
rangeCheck(areaCode,999,"area code");
rangeCheck(exchange,999,"exchange");
rangeCheck(extension,9999,"extension");
this.areaCode=(short)areaCode;
this.exchange=(short)exchange;
this.extension=(short)extension;
}
private static void rangeCheck(int arg,int max,String name){
if(arg<0||arg <max)
try {
throw new Exception();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//not hashcode method
}
public boolean equals(Object o){
if(o==this){
return true;
}
if(!(o instanceof PhoneNumber))
return false;
PhoneNumber pn=(PhoneNumber)o;
return pn.extension==extension &&
pn.exchange==exchange &&
pn.areaCode==areaCode;
}
// public int hashCode(){
// int result=17;
// if(hashCode==0){
// result=37*result+areaCode;
// result=37*result+exchange;
// result=37*result+extension;
// hashCode=result;
// }
// return result;
// }
public static void main(String[] args){
PhoneNumber ph=new PhoneNumber(408,867,5309);
PhoneNumber ph1=new PhoneNumber(408,867,5309);
System.out.println(ph.equals(ph1));
System.out.println(ph.hashCode());
System.out.println(ph1.hashCode());
}
}
此例如果不实现hashCode方法就会造成:equals相等hashcode不相等 所以在自己实现对象时候必须实现hashCode()方法。哎,这位主管大人还说:可能JDK里自带对象都相等,自己生成的复杂对象可以不相等。 我晕!估计他连hash值有啥作用还很模糊!基本功可见一般!