深入剖析hashCode和equals的区别及大厂面试题

关于作者:毕业半年被裁,一个月斩获大厂offer,面试经验50+。“跟着周哥走,offer手里有”。文末免费领取周哥50+场面试总结出的必背面试题。

首先我们要知道,equals()和hashCode()都属于Object类,而Object类是所有类(包括Class)的父类。

搞清楚这一点,再分别解析equals和hashCode,然后作出对比。最后,给出关于equals和hashcode重要面试题及答案。

equals()解析

  • 作用:用于引用数据类型,判断一个对象是否等于另一个对象,可以重写 equals 方法自定义比较规则。

  • ==和equals的区别

    • 如果变量是基本数据类型,那么使用==比较变量的值。
    • 如果变量是引用数据类型,==仍然比较变量的值(不忘初心),只不过这个值是对象的地址。
    • equals只能作用于引用数据类型。 equals如果没有重写,比较的是引用变量的值,即对象地址。equals重写之后,比较的是对象的内容。例如使用equals比较String的value值是否相等。

hashCode()解析

  • 作用:hashCode() 的作用是获取哈希码,也称为散列码,其作用是将对象的地址值(即引用变量)映射为integer类型的哈希值。这个哈希码的作用是确定该对象在哈希表中的索引位置。

注意,字符串(String类型)可能有相同的散列码。这是由于String类型中重写了hashcode方法。
看下图可知,String类型的字符串值是保存在value中的。而value会保存在字符串常量池中。



比如,

s1 = "123";
s2 = "123";

s1和s2的引用变量,即对象的地址,是不同的。但由于s1和s2的引用对象的value数组值是相同的。故,在计算哈希值时,s1和s2的就会得到相同的哈希值。

hashCode()和equals()面试题解析

1. hashCode() 和 equals() 两种方法之间有什么关系?

答:

为了在集合类HashMap或HashSet中正确使用散列码,需同时重写 equals 和 hashCode 方法。

两对象比较时,先比较hashCode后比较equals。equals 相同时 hashCode 必相同,但 hashCode 相同时 equals 未必相同。hashCode 是两个对象相同的必要不充分条件。
即:

       equals相同<=>对象相同

       对象相同=>hashcode相同

    逆否命题:hashCode不同=>对象不同

2. 为什么hashcode相同时,equals不一定相同?

答:有时候不同的对象,hashcode的值可能也会相同,例如:


所以说,hashCode()并不可靠。
equals由于比较的是对象的值,值相同与否是可以确定的,所以是可靠的。

3. 为什么不直接equals比较值是否相同,而先要计算hashCode?

答:
hash算法是二进制算法,计算式本质是二进制,所以hash算法速度很快。如若hashCode不同则可直接存储不用equlas比较。所以先计算hashCode大大加快了存储速率。

4. 为什么重写equals后必须重写hashcode?
答:

Object类的equals()方法上方的注释里有写到:当我们将equals方法重写后有必要将hashCode方法也重写,这样做才能保证不违背hashCode方法中“相同对象必须有相同哈希值”的约定。

由此可见,重写equals后必须重写hashcode是为了保证重写后的equals方法认定相同的两个对象拥有相同的哈希值。

至于equals相同hashcode也必须相同的原因,是为了与Java集合配套使用。

我们可以以hashSet实现去重功能为例,hashSet底层是通过HashMap来实现的,查看源码可以发现HashMap中的Hash()方法,是调用了key.HashCode()。

我们假设自定义一个学生类型Student,且Student只重写了equals方法。然后,new出两个属性值完全一样的对象,将其先后添加到HashSet中。
查看HashMap中的putVal()方法可知,

会将传入学生对象的hash值与(数组长度-1)进行&操作,得到数组的下标值。但是由于学生类型,没有重写hashCode,则其hashcode()方法默认是通过对象的地址值的得出。

由于两个学生对象的地址值不同,因此哈希值不同。那么,根据哈希值计算出的索引位置就会不同,则会将两个学生对象存入不同的数组位置。但是,由于equals是根据学生信息计算的,所以equals是相同的。这就违背了hashset的去重功能(hashset不会将相同的对象存到数组中)。因此,必须重写HashCode()方法。

5.会自定义子类重写equals吗?

答:示例如下

好了,到此为止,关于hashcode和equals的知识点大家应该有个深刻的理解了。

点击此处,获取面试秘籍

本文由mdnice多平台发布

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值