java重写equals方法时,为何需要重写hashCode方法?

假如是在hashMap中存入数据,并且没有重写hashCode方法:

现在有两条相同的数据,但是因为hash值不同,两个对象都会存入map中,如下:

public class Test1 {
     
    public static void main(String[] args) {
     
        //实例化两个学生对象
        Student s1 = new Student();
        Student s2 = new Student();
        System.out.println("s1.equals(s2):" + s1.equals(s2));   //比较两个对象是否一样,结果为false
        //这两个对象的hash值不同
        System.out.println("s1.hashCode():" + s1.hashCode());
        System.out.println("s2.hashCode():" + s2.hashCode());
        //s2不会覆盖s1的值
        Map<Student, String> temp = new HashMap<>();
        temp.put(s1, "s1");
        temp.put(s2, "s2");
        System.out.println("temp.get(s1): " + temp.get(s1));
        System.out.println("temp.get(s2): " + temp.get(s2));
        System.out.println("temp.size(): " + temp.size());
    }
}

class Student {
     
    private String name;
    private String phone;

    @Override
    public boolean equals(Object o) {
     
        if (this == o) return true;
        if (!(o instanceof Student)) return false;
        Student student = (Student) o;
        return Objects.equals(name, student.name) &&
                Objects.equals(phone, student.phone);
    }

    //@Override
    //public int hashCode() {
     
    //    return Objects.hash(name, phone);
    //}
}

java重写equals方法时,为何需要重写hashCode方法?_第1张图片
很明显这不是我们想要的结果,因为map中的数据重复了,这时候就需要重写hashCode方法,然后后面存入的对象会覆盖掉前一个equals比较结果为true的对象。
这里不放代码了,只是把重写的hashCode方法的注释去掉了,结果如下:java重写equals方法时,为何需要重写hashCode方法?_第2张图片
s1和s2的hash值一样。
可以看到map的size为1,里面只有一对键值对。s1和s2的hash值一样,所以会有覆盖现象。

结论:正常开发中,存在着在hashMap中存入了相重复数据,此时有可能是因为没有重写hashCode方法导致的。根据hashCode 的规则,相同对象的hash值一定相同,这样是为了避免上述矛盾的产生。所以在重写了equals方法的时候,最好也要重写hashCode方法。

p.s. 根据hashCode的规则:
hash值相同,对象不一定相同(在极低的概率下,不同的对象是有可能计算出相同的hash值的);
hash值不同,对象一定不相同;(和下面一条互为逆反命题)
对象相同,hash值一定相同;(和上面一条互为逆反命题)
对象不同,hash值可能相同。

p.p.s equals和hashCode方法比起来,消耗的资源要多些。所以先比较hashCode,若是不同,不用往下比了,两个对象一定不相同。如果相同,还需要比较equals。

你可能感兴趣的:(java,java)