Java:你不知道的那些事(三)——为什么重写equals还要重写hashCode

引言

在面试题中,关于equals的问题可以说是很常见的了,例如:
1、equals和 == 有什么区别?
2、hashcode相等的两个对象一定==相等吗?equals相等吗?
3、两个对象用equals比较相等,那它们的hashcode相等吗?
关于问题一,我会在博客的末尾附上我的另一篇博客链接。本篇博客重点探究问题二和问题三。

探究

Person 类:

public class Person
{
    private String name;

    private int age;

    private String sex;

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

    @Override
    public boolean equals(Object obj)
    {
        if(obj instanceof Person){
            Person person = (Person)obj;
            return name.equals(person.name);
        }
        return super.equals(obj);
    }

    @Override
    public int hashCode()
    {
        return name.hashCode();
    }
}

测试类:

public class HashTest {

    public static void main(String[] args)
    {
        HashMap<Person, Integer> map = new HashMap<Person, Integer>();

        Person p = new Person("jack",22,"男");
        Person p1 = new Person("jack",22,"男");

        System.out.println("p的hashCode:"+p.hashCode());
        System.out.println("p1的hashCode:"+p1.hashCode());
        System.out.println(p.equals(p1));
        System.out.println(p == p1);

        map.put(p,888);
        map.put(p1,888);
        map.forEach((key,val)->{
            System.out.println(key);
            System.out.println(val);
        });
    }
}
情况一:二者均不重写

注释掉Person的equals和hashCode,输出
在这里插入图片描述

Object 类的 equals 源码
在这里插入图片描述
Object 类的 hashCode 源码
在这里插入图片描述

由 Object 类的源码以及 hashCode 的计算来源可以得知,它们的表现是一致的,都是比较两个变量的内存地址是否相等。由于这两个方法都没有重写,判定这两个对象是不同的,放在不同的索引之下。(用的都是父类的方法)

情况二:equals重写,hashCode不重写

注释掉Person的hashCode,输出
在这里插入图片描述

由上面的结果可知,通过重写的 equals 方法判定,这两个对象应该放在 hash 表的同一个索引之下。但由于我们建了两个不同的对象,得到了两个不同的地址,而且我们没有重写 hashCode 方法,所以这两个对象会放在不同的索引之下。这样的话就会与hash的设计相冲突,导致整个 hash 结构无法正常工作。(子类的equals,父类的hashCode)

情况三:equals不重写,hashCode重写

注释掉Person的equals,输出
在这里插入图片描述

这就与情况二类似,通过重写的 hashCode方法判定,这两个对象应该放在 hash 表的同一个索引之下。但由于我们建了两个不同的对象,得到了两个不同的地址,而且我们没有重写 equals 方法,判定这两个是不相同的,所以这两个对象会放在不同的索引之下。这样的话就会与hash的设计相冲突,导致整个 hash 结构无法正常工作。(父类的equals,子类的hashCode)

情况四:equals和hashCode都重写

在这里插入图片描述

我们通过重写的 equals 和 hashCode 判定得出,它们应该放在 hash 表的同一个索引之下,二者的表现一致,符合 hash 结构的设计理念。

问题解答

回到最开始的问题:
1、hashcode相等的两个对象一定==相等吗?equals相等吗?
2、两个对象用equals比较相等,那它们的hashcode相等吗?

由上面的探究可以得出:
两个对象==相等,则其hashcode一定相等,反之不一定成立。
两个对象equals相等,则其hashcode一定相等,反之不一定成立。
【注:hashCode 是由对象的内部地址经过 hash 函数得到的】

总结

本博客为个人的理解总结而来,如果有不对的地方,欢迎指出来,一起共同进步!!!

问题一:从源码角度解析 “==” 和 equals 关于引用数据类型方面的区别
参考链接:
1、hashcode相等的两个对象一定 == 相等么?equals相等么?
2、为什么重写equals必须重写hashCode

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

--流星。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值