前往小程序,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 删除。

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
equals() ? ==? hashCode()? 今天就把你们都认识清楚
byte,short,char,int,long,float,double,boolean 他们之间的比较,应用双等号(==),基础数据类型比较的是他们的值。
Java宝典
2021/04/22
4530
Java 中的 ==, equals 与 hashCode 的区别与联系
这句话声明了一个引用类型的变量,此时它并没有和任何对象关联。   而通过 new 来产生一个对象,并将这个对象和str1进行绑定:
heasy3
2020/08/03
1.5K0
浅谈equals、hashcode、==
==和equals和hashcode是经常遇到但是很重要的内容,希望这篇文章能帮你理清概念。
崩天的勾玉
2021/12/20
6700
重写equals方法必须重写hashcode
比较的是引用,也就是对象的地址是否相等,equals在非空对象上需要满足以下特性:
用户4415180
2022/06/23
1.3K0
java为什么要重写hashCode和equals方法
      在我们的业务系统中判断对象时有时候需要的不是一种严格意义上的相等,而是一种业务上的对象相等。在这种情况下,原生的equals方法就不能满足我们的需求了。
业余草
2019/01/21
2.9K0
面试题:重写equals方法为什么通常会重写hashcode方法?
最近在面试的时候,当问完了HashMap的数据结构之后,通常会再多问一个问题,就是:重写equals方法时通常为什么也要重写一下hashcode方法?
程序新视界
2021/03/22
6940
Java中的equals()和hashCode() - 超详细篇
大家好啊,我是汤圆,今天给大家带来的是《Java中的equals()和hashCode() - 详细篇》,希望对大家有帮助,谢谢
汤圆学Java
2021/04/10
7200
Java中的equals()和hashCode() - 超详细篇
详解equals()方法和hashCode()方法
Java的基类Object提供了一些方法,其中equals()方法用于判断两个对象是否相等,hashCode()方法用于计算对象的哈希码。equals()和hashCode()都不是final方法,都可以被重写(overwrite)。
Java团长
2018/08/06
4140
java中equals,hashcode和==的区别
byte,short,char,int,long,float,double,boolean 他们之间的比较,应用双等号(==),比较的是他们的值。
Anymarvel
2019/03/04
1.4K0
java中equals,hashcode和==的区别
为什么重写 equals 方法时必须同时重写 hashCode 方法?
本文由 Java 中常见的面试题「为什么重写 equals 方法时必须同时重写 hashCode 方法?」所引出。渐进式探讨关于 hashCode 的三个问题:hashCode 方法的作用以及 hashCode 方法与 equals 方法的关系?为什么重写 equals 方法时必须同时重写 hashCode 方法?以及如何重写 hashCode 方法?
每周聚焦
2024/10/28
880
为什么重写 equals 方法时必须同时重写 hashCode 方法?
equals 和 hashCode 到底有什么联系?一文告诉你!
Java的基类Object提供了一些方法,其中equals()方法用于判断两个对象是否相等,hashCode()方法用于计算对象的哈希码。equals()和hashCode()都不是final方法,都可以被重写(overwrite)。
Java技术栈
2018/07/30
6730
equals 和 hashCode 到底有什么联系?一文告诉你!
【Java提高十二】hashCode()equals()
hashCode的作用 要想了解一个方法的内在原理,我们首先需要明白它是干什么的,也就是这个方法的作用。在讲解数组时,我们提到数组是java中效率最高的数据结构,但是“最高”是有前提的。第一我们需要知道所查询数据的所在位置。第二:如果我们进行迭代查找时,数据量一定要小,对于大数据量而言一般推荐集合。 在Java集合中有两类,一类是List,一类是Set他们之间的区别就在于List集合中的元素师有序的,且可以重复,而Set集合中元素是无序不可重复的。对于List好处理,但是对于Set而言我们要如何来保证元
Java帮帮
2018/03/15
7850
【Java提高十二】hashCode()equals()
JAVA中重写equals()方法为什么要重写hashcode()方法说明
重写hashCode()时最重要的原因就是:无论何时,对同一个对象调用hashCode()都应该生成同样的值。如果在将一个对象用put()方法添加进HashMap时产生一个hashCode()值,而用get()取出时却产生了另外一个 hashCode()值,那么就无法重新取得该对象了。所以,如果你的hashCode()方法依赖于对象中易变的数据,那用户就要小心了,因为此数据发生变化时,hashCode()就会产生一个不同的hash码,相当于产生了一个不同的“键”。        Object的hashCode()方法,返回的是当前对象的内存地址。下次如果我们需要取一个一样的“键”对应的键值对的时候,我们就无法得到一样的hashCode值了。因为我们后来创建的“键”对象已经不是存入HashMap中的那个内存地址的对象了。        我们看一个简单的例子,就能更加清楚的理解上面的意思。假定我们写了一个类:Person (人),我们判断一个对象“人”是否指向同一个人,只要知道这个人的身份证号一直就可以了。        先来个没有重写Code类的hashcode()的例子吧,看看是什么效果:
bear_fish
2018/09/20
1.1K0
JAVA中重写equals()方法为什么要重写hashcode()方法说明
如何编写出高质量的 equals 和 hashcode 方法?
这要从 Object 类开始说起,我们知道 Object 类是 Java 的超类,每个类都直接或者间接的继承了 Object 类,在 Object 中提供了 8 个基本的方法,equals 方法和 hashcode 方法就是其中的两个。
淡定的蜗牛
2019/09/29
6240
如何编写出高质量的 equals 和 hashcode 方法?
Java基础提升篇:equals()与hashCode()方法详解
概述 java.lang.Object类中有两个非常重要的方法: 1public boolean equals(Object obj) 2public int hashCode() 3 Object类是类继承结构的基础,所以是每一个类的父类。所有的对象,包括数组,都实现了在Object类中定义的方法。 equals()方法详解 equals()方法是用来判断其他的对象是否和该对象相等. equals()方法在object类中定义如下: 1public boolean equals(Object obj)
好好学java
2018/07/02
4110
java中hashcode的用法_javahashcode作用
hashcode()是干什么用的?首先hashcode是哈希算法的一中简单实现,他是一个对象的哈希吗值。一般和equals一起使用。
全栈程序员站长
2022/10/03
9710
为什么重写equals必须重写hashCode
如果我们不重写equals和hashcode,那么它使用的是Object方法的实现。我们先简单看一下
一个程序员的成长
2021/12/08
1.7K0
JAVA-为什么equals和hashcode在重写时要保持一致
在java中equals方法是写在Object类中的,这个方法是用来检测一个对象是否等于另一个对象。在Object类中这个方法判断两个对象是否具有相同的引用。
用户7886150
2020/12/07
4930
面试官:为什么重写 equals 同时要重写 hashCode? 我:…
重写equals是为了在业务逻辑上判断实例之间是否相等。重写hascode是为了让集合快速判重。
终码一生
2022/04/14
2880
为什么要重写 hashCode 和 equals 方法?
心里想着我没事重写哪玩意干啥,能不写就不写。嘴上当然没敢这么说,只能略表遗憾的说抱歉,我没写过。
周三不加班
2019/06/04
5210
为什么要重写 hashCode 和 equals 方法?
推荐阅读
相关推荐
equals() ? ==? hashCode()? 今天就把你们都认识清楚
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文