为什么重写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可以相同(只不过会发生哈希冲突,应尽量避免)。

posted @ 2019-12-18 11:37  gaopengpy  阅读(323)  评论(0编辑  收藏  举报