为什么重写equals方法需同时重写hashCode方法?
举个小例子来看看,如果重写了equals而不重写hashcode会发生什么样的问题:
import java.util.HashMap; public class MyTest { private static class Person { int idCard; String name; public Person(int idCard, String name) { this.idCard = idCard; this.name = name; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Person person = (Person) o; // 两个对象是否等值,通过idCard来确定 return this.idCard == person.idCard; } } public static void main(String[] args) { HashMap<Person, String> map = new HashMap<Person, String>(); Person person = new Person(1234, "乔峰"); // put到hashmap中去 map.put(person, "天龙八部"); // get取出,从逻辑上讲应该能输出“天龙八部” System.out.println("结果:" + map.get(new Person(1234, "萧峰"))); } }
运行结果:
结果:null
如果我们已经对HashMap的原理有了一定了解,这个结果就不难理解了。尽管我们在进行get和put操作的时候,使用的key从逻辑上讲是等值的(通过equals比较是相等的),但由于没有重写hashCode方法,所以put操作时,key(hashcode1)-->hash-->indexFor-->最终索引位置 ,而通过key取出value的时候 key(hashcode1)-->hash-->indexFor-->最终索引位置,由于hashcode1不等于hashcode2,导致没有定位到一个数组位置而返回逻辑上错误的值null(也有可能碰巧定位到一个数组位置,但是也会判断其entry的hash值是否相等,上面get方法中有提到。)
所以,在重写equals的方法的时候,必须注意重写hashCode方法,同时还要保证通过equals判断相等的两个对象,调用hashCode方法要返回同样的整数值。而如果equals判断不相等的两个对象,其hashCode可以相同(只不过会发生哈希冲突,应尽量避免)。