前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >为什么重写了equals()也要重写hashCode()

为什么重写了equals()也要重写hashCode()

作者头像
公众号 IT老哥
发布于 2020-12-29 07:31:47
发布于 2020-12-29 07:31:47
1K00
代码可运行
举报
运行总次数:0
代码可运行

前言

在Effective Java中第九条规定在覆盖equals()方法时总要覆盖hashCode()方法。这是为什么呢?接下来我们就介绍一下这两个方法。

Java中的equals()方法和hashCode()方法都是在Object类中的方法,而在Java中所有的类都是Obejct类的子类,所以Java中所有的方法都会有这两个方法的默认实现。

equals方法

Object类中的equals()方法定义如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public boolean equals(Object obj) {
    return (this == obj);
}

我们发现在equals()方法中就关键的==,那么==在Java中有什么含义呢。

我们都知道在Java中分为基本数据类型和引用数据类型。那么==在这两个类型中作用是不一样的。

  • 基本数据类型:比较的是==两边值是否相等
  • 引用数据类型:比较的是==两边内存地址是否相等

基本数据类型包括:byteshortcharintlongfloatdoubleboolean

而通过Java文档中的equals()方法描述,所有要实现自己的equals()方法都要遵守下面几个规则

  • 自反性:对于任何对象x,x.equals(x)应该返回true
  • 对称性:对于任何两个对象x和y,如果x.equals(y)返回true,那么y.equals(x)也应该返回true
  • 传递性:对于多个对象x、y、z,如果x.equals(y)返回true,y.equals(z)返回true,那么y.equals(z)也应该返回true
  • 一致性:对于两个非空对象x、y,在没有修改此对象的前提下,多次调用返回的结果应该相同
  • 对于任何非空的对象x,x.equals(null)都应该返回false

hashCode方法

Object中的hashCode()方法是一个本地方法,返回一个int类型的哈希值。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public native int hashCode();

在hashCode()方法中也有一些规约

  • 如果对象在使用equals方法中进行比较的参数没有修改,那么多次调用一个对象的hashCode()方法返回的哈希值应该是相同的。
  • 如果两个对象通过equals方法比较是相等的,那么要求这两个对象的hashCode方法返回的值也应该是相等的。
  • 如果两个对象通过equals方法比较是不同的,那么也不要求这两个对象的hashCode方法返回的值是相同的。但是我们应该知道对于不同对象产生不同的哈希值对于哈希表(HashMap等等)能够提高性能。

equals方法和hashCode方法会在哪用到

这两个方法经常出现在Java中的哪个类里面呢?如果看过HashMap源码的应该了解这两个方法经常出现在HashMap中。

网上介绍HashMap类的文章有很多了,这里就简单介绍一下HashMap。

当一个节点中的链表超过了8的时候就会变为红黑树,以解决链表长度过长以后查询速度慢的缺点。

HashMap是由数组和链表组成的高效存储数据的结构。那么是如何确定一个数据存储在数组中的哪个位置呢?

就是通过hashCode方法进行计算出存储在哪个位置,还记得我们上面讲hashCode方法说了有可能两个不同对象的hashCode方法返回的值相同。

那么此时就会产生冲突,产生冲突的话就会调用equals方法进行比对,如果不同,那么就将其加入链表尾部,如果相同就替换原数据。

计算位置当然不是上面简单的一个hashCode方法就计算出来,中间还有一些其他的步骤,这里可以简单的认为是hashCode确定了位置。

什么时候去覆盖这两个方法呢?

如果你不将自定义的类定义为HashMap的key值的话,那么我们重写了equals方法而没有重写hashCode方法,编译器不会报任何错,在运行时也不会抛任何异常。

如果你想将自定义的类定义为HashMap的key值得话,那么如果重写了equals方法那么就必须也重写hashCode方法。

接下来我们可以看一下我们使用自定义的类作为HashMap的key,并且自定义的类不重写equals和hashCode方法会发生什么。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Builder
@NoArgsConstructor
@AllArgsConstructor
class CustomizedKey{
    private Integer id;
    private String name;
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static void main(String[] args) {

    Map<CustomizedKey, Integer> data = getData();

    CustomizedKey key = CustomizedKey.builder().id(1).name("key").build();

    Integer integer = data.get(key);

    System.out.printf(String.valueOf(integer));
}

private static Map<CustomizedKey,Integer> getData(){
    Map<CustomizedKey,Integer> customizedKeyIntegerMap = new HashMap<>();
    CustomizedKey key = CustomizedKey.builder().id(1).name("key").build();
    customizedKeyIntegerMap.put(key,10);
    return customizedKeyIntegerMap;
}

我们可以看到程序最后打印的是一个null值。原因正如上面我们说的一样。

hashCode:用来计算该对象放入数组中的哪个位置,因为是两个都是new的对象,所以即使里面的值一样,但是对象所处的地址却不同,所以使用默认的hashCode也就不同,当然在hashMap中就不会认为两个是一个对象。

接下来我们就重写一下这两个方法。如果我们使用IDEA的话,那么直接使用快捷键即可。

接下来我们看我们实现的两个方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Builder
@NoArgsConstructor
@AllArgsConstructor
class CustomizedKey{
    private Integer id;
    private String name;

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

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

然后我们再次运行上面的程序发现输出打印已经变成了10。

源于:jianshu.com/p/53e233e8abad

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-12-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IT老哥 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
你关电脑么?
作为IT人员,每天接触最多的办公设备可能就是电脑了,台式机、笔记本、各种Pad,非常"日常"的一个问题就是你下班了关电脑么?
bisal
2022/09/22
5770
你关电脑么?
巧用Powershell命令查看Win10电脑上次关机方式
了加快Windows系统的开机速度,微软自Windows8开始引入了“快速启动”机制,并且延用到了最新的Windows10系统上。启用该机制后, 再关机时就融合了休眠的特性,可以有效地提高开机的速度,我们把这种关机方式称之为“混合”关机。 这样Win10的关机方式就有了三种:完全关机、混合关机和休眠。 对于一些使用过win10系统的用户来说,其系统的开机与关机速度是其它系统都不可相比的,但是很多用户却不知道win10系统的关机与开机方式是与win7、XP有所不同的,在win10系统下,关机模式采用混合方式,来达到快速开%9
P轴
2022/11/18
5890
硬件笔记之英特尔NUC无法进入BIOS
英特尔NUC在bios内开启fast boot快速启动后,在后续使用中开机按F2键无法进入bios;
Jetpropelledsnake21
2021/07/08
6.3K0
轻松解决Win10电脑关机不彻底的问题
今天在群里看到有人说WIN10关机只是深度睡眠,系统没有完全关闭,我比较感兴趣,特意了解了下,给大家分享一下。
半夜喝可乐
2021/09/08
9.5K0
轻松解决Win10电脑关机不彻底的问题
Win11电脑如何设置每天早上定时自动开机?6大方案详解+多系统攻略
想知道Win11怎么设置定时自动开机提升办公效率?本文为您揭秘5种100%有效的自动开机方案,涵盖Windows专属设置、笔记本品牌攻略、Linux/Mac跨系统教程,更有通用解决方案和避坑指南!立即收藏这份全网最全的自动开机设置宝典,让您的电脑每天准时唤醒迎接工作!
猫头虎
2025/01/27
2.6K0
Win11电脑如何设置每天早上定时自动开机?6大方案详解+多系统攻略
春节来临:Windows & Mac 电脑设置自动开机、永不休眠、远程解决方案与远程办公指南
春节将至,对于许多人来说,这不仅是一段与家人团聚的美好时光,同时也可能是需要兼顾远程工作的关键时期。为了帮助大家在春节期间实现设备高效管理和远程办公,本文将从以下几个方面进行详细讲解:
猫头虎
2025/01/18
3520
春节来临:Windows & Mac 电脑设置自动开机、永不休眠、远程解决方案与远程办公指南
电脑知识系列之(八)------技能分享
分享文章之前,先为大家带来一首老歌,希望大家听了,能有更多的收获,并以更加饱满的热情迎接明天的到来和勇敢的去面对未来的种种挑战,最终获得属于我们的成功,转瞬间却发现,一笑已经风云过。。。。。。。
用户5410712
2022/06/01
2990
电脑知识系列之(八)------技能分享
Linux系统-开关机
作者介绍:简历上没有一个精通的运维工程师。请点击上方的蓝色《运维小路》关注我,下面的思维导图也是预计更新的内容和当前进度(不定时更新)。
运维小路
2024/11/01
930
Linux系统-开关机
启动计算机配置windows7,win7开机显示准备配置Windows请勿关闭计算机 然后无限重启怎么回事…
win7开机显示准备配置Windows请勿关闭计算机 然后无限重启怎么回事以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
全栈程序员站长
2022/07/05
2.5K0
启动计算机配置windows7,win7开机显示准备配置Windows请勿关闭计算机 然后无限重启怎么回事…
Win10系统电源管理中没有快速启动怎么回事
接着刚才的话题,安装完操作系统之后发启动的速度并没有什么变化,感觉是快了些,但是腾讯电脑管家不显示开机时间,看来得设置下,打开电脑管家软件,点击右上角(三条横线)菜单,打开设置中心,常规设置选项卡,勾选总是弹出,然后确定,如图:
李洋博客
2021/06/15
1.7K0
win10电脑休眠后无法唤醒的解决办法
  电脑的休眠功能,为长时间不用的电脑进行了关闭显示、硬盘停转的深度节能模式,不仅节约能源,还保护设备。
黑泽君
2018/12/12
6.9K0
电脑定时开机方法「建议收藏」
首先开机后按住Delete键,就是平常常用的删除按键(见图1),然后就会进入到BIOS界面。虽然是一个满眼E文的蓝色世界,但不要害怕,没有问题的。 图2 在BIOS设置主界面中选择“Power”选项(见图2),进入电源管理窗口。有些机器是在“Power Management Setup”里面。 图3 默认情况下,“Automatic Power Up(定时开机,有些机器选项为Resume By Alarm)”选项是关闭的,将光标移到该项(见图3),用“Pagedown”键将“Disabled”改为“Enabled”。 图4 此时“Automatic Power Up”选项会弹出一个菜单,里面有三项选择:“Disabled、Every Day和By Date”(见图4),意思是“禁止、每天和指定日期”。对于上班族来说,我们推荐第二项,这时会跳出一个日期和时间设置。 图5 恭喜您,大功已经告成一半了,这时将光标先移到“Time Alarm(开机时间)”上,用“Pageup”、“Pagedown”设定好(见图5)。如果您设定的是制定日期,则还要在“Date Alarm(开机日期)”上做一个设定。当然,不同的主板功能有差异,有的每设置一次,只能使用一次,而有的可以设置一个周期。 图6 最后一步了,这回真的要大功告成了,就是选择“Exit Saving Changes”(见图6),保存并退出,大部分机器都有热键,一般都是F10。接着机器会重新启动,OK,恭喜你,你的机器可以自动上班了。 怎么样,你现在的机器是否可以每天自动开工了呢,当然前提是你也不要迟到呀,否则就算它开机了还是在那里漫长的等待,别指望它能自己干活呦。最后提醒大家一句,就是在周末的时候一定要想着关闭电源,否则周六它还是会按时开机的,虽然可以再设BIOS关闭,但总归没有关闭电源来的容易,您说呢
全栈程序员站长
2022/09/20
4.4K0
如何启用计算机的休眠,电脑休眠
在休眠时可以完全断开电脑的电源,自动关闭显示器和硬盘的时间设置为多长时间比较合适应看你需要了。
全栈程序员站长
2022/09/14
2K0
苹果Mac重置SMC、NVRAM、PRAM的方法
虽然苹果Mac相对于Windows系统崩溃的几率已经小很多了,但还是会碰到一些特殊情况,比如说Mac突然变得非常卡顿、耗电等情况,而这个时候像Windows那样简单的重启已经不能解决问题。如果联系苹果的技术支持,大多数时候他们都会先引导尝试重置SMC、PRAM和NVRAM等措施。
子润先生
2021/06/24
26.7K0
教你不花一分钱,用十分钟把旧电脑打造成自己的Windows版NAS系统
一年前我前前后后花了2个多星期的时间才将整套系统部署完成,但这是因为其中有很多的坑,需要找到解决方案。我已经尽可能把过程中遇到的所有问题都写明,大家只要跟着去做,还是非常简单的,不需要太长时间。整套系统至今一直非常稳定。
ICT系统集成阿祥
2024/12/30
4.7K0
教你不花一分钱,用十分钟把旧电脑打造成自己的Windows版NAS系统
Mac三分之一 系统初尝
https://www.apple.com/cn/shop/product/FPXT2CH/A
acc8226
2022/05/17
1.2K0
Mac三分之一 系统初尝
家庭实验室系列文章-电脑如何配置网络唤醒 (WOL)?
前言 其实这个专题很久很久之前就想写了,但是一直因为各种原因拖着没动笔。 因为没有资格,也没有钱在一线城市买房 (😂😂😂); 但是在要结婚之前,婚房又是刚需。 我和太太最终一起在一线城市周边的某二线城市买了房。 再之后,一起装修,她负责非电相关,我负责电 网相关的装修。 家庭组网,家庭实验室就这么一步一步随着家庭的组建而组建了起来: 家庭有线无线组网 智能家居 NAS 公网 IP 和 IPv6 Wake Online (WOL) 家庭网络安全 (😂看了防火墙日志,才知道被攻击频率能有多高) 玩转树莓派 组
东风微鸣
2022/12/01
3.9K0
家庭实验室系列文章-电脑如何配置网络唤醒 (WOL)?
解决 Windows10 笔记本关上后仍会掉电的问题
一开始我只是想在谷歌上搜索一下,为啥我的 Win10 笔记本在盖上盖子以后放入背包中,每次拿出来之后电量都会有所下降,结果就一下子看到了很多很神奇的东西,包括 Win10 的几种节能状态,以及如何设置关闭盖子的行为。且听我一一道来。
Allen Cheng
2018/09/10
12.2K0
解决 Windows10 笔记本关上后仍会掉电的问题
学校Seewo电脑与机房电脑研究报告
2021.11.13:wim在Whitemu-PC上释放成功并可正常开机,此时正式开始更多的获取到系统信息
Moemu
2023/05/04
1.4K0
学校Seewo电脑与机房电脑研究报告
Android电源管理基础知识整理
要理解第一个问题,得先从ACPI(高级配置与电源接口)说起,ACPI是一种规范(包含软件与硬件),用来供操作系统应用程序管理所有电源接口。
233333
2020/01/02
5.5K0
推荐阅读
相关推荐
你关电脑么?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验