一文就带你搞懂✨为什么重写 equals 时必须重写 hashCode 方法?

1,258 阅读2分钟

这是我参与8月更文挑战的第22天,活动详情查看:8月更文挑战

⭐8月更文挑战第22天⭐,和小伙伴们一起复习巩固Java😁

Code皮皮虾 一个沙雕而又有趣的憨憨少年,和大多数小伙伴们一样喜欢听歌、游戏,当然除此之外还有写作的兴趣,emm...,日子还很长,让我们一起加油努力叭🌈

欢迎各位小伙伴们关注我的公众号:JavaCodes,名称虽带Java但涉及范围可不止Java领域噢😁,会长期分享博文或者福利,期待您的关注❤

详文链接

😉毛遂自荐

毛遂自荐,给大家推荐一下自己的专栏😁,欢迎小伙伴们收藏关注😊

小白学Java

MybatisPlus专栏

App爬虫专栏

PC端爬虫专栏

大厂面试题专栏


🔥整体结构图

在这里插入图片描述


✨前景说明

==为什么重写 equals 时必须重写 hashCode 方法?==

相信这个问题大部分小伙伴即使面试中没有被问到过,但肯定也听说过

==那么这个问题到底是为什么?该怎么回答?今天我皮皮虾就来告诉各位小伙伴们==🌈

当然,如果对各位有那么亿点点小作用的话,那么期待大家的一键三连哦!😊



⭐为什么?有什么作用OR好处?

  1. 使用hashcode方法提前校验,可以避免每一次比对都调用equals方法,提高效率

    例如 HashSet是具有不可重复性的,每次往里面添加数据时,都会先计算该数据的 哈希值(即在哈希表中的存放位置),然后与set中已经存在的数据的 哈希值进行比较,如果都不同则添加在计算出的位置进行添加,如果相同则调用 equals方法进行判断,相同则不添加,不相同则散列到其他位置添加。

    因为不同对象出现 哈希值相同的概率是比较低的,所以重写了 hashcode方法可以减少 equals方法的调用,提高效率。

  2. ==保证同一个对象,保证在equals相同的情况下hashcode值必定相同==,如果重写了equals而未重写hashcode方法,可能就会出现两个没有关系的对象equals相同的(因为equal都是根据对象的特征进行重写的),但hashcode不相同,这样就不符合期望。


🚀实战演练


没有重写hashcode()

public class test {


    public static void main(String[] args) {
        HashSet<User> users = new HashSet<>();
        users.add(new User(10,"111"));
        users.add(new User(10,"111"));

        for (User i : users) {
            System.out.println(i);
        }
    }

}

class User {
    int age;
    String name;

    public User(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return age == user.age &&
                Objects.equals(name, user.name);
    }

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

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

在这里插入图片描述

为什么会这样?

前文已经提过:==保证同一个对象,保证在equals相同的情况下hashcode值必定相同==,因为自定义对象都是==new==出来的,所以地址不同,那么==hashCode==很大概率不同,所以不会出现==哈希冲突==,就不会调用==equals==去进行判断,那么这两个==特征相同的对象(也就是我们觉得应该是一样的对象)== 就成功加入到HashSet中去了。


解决办法:重写hashcode()

public class test {


    public static void main(String[] args) {
        HashSet<User> users = new HashSet<>();
        users.add(new User(10,"111"));
        users.add(new User(10,"111"));

        for (User i : users) {
            System.out.println(i);
        }
    }

}

class User {
    int age;
    String name;

    public User(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return age == user.age &&
                Objects.equals(name, user.name);
    }

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

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

可见对象被判定为重复,所以只有一份。

原理解析:==因为重写了hashCode方法,那么对于特征相同的对象,那么他们的hash值是一样的,所以会出现hash冲突,出现了hash冲突就会去调用equals方法进行判断是否为同一个对象,因为重写了equals方法,那么这两个对象被判定为重复,所以HashSet里面只有一份。==


❤最后

我是 Code皮皮虾,一个热爱分享知识的 皮皮虾爱好者,未来的日子里会不断更新出对大家有益的博文,期待大家的关注!!!

创作不易,如果这篇博文对各位有帮助,希望各位小伙伴可以==一键三连哦!==,感谢支持,我们下次再见~~~


一键三连.png