在java中为什么重写equals要重写hashcode

 为什么重写equals要重写hashcode

在Java中,当我们重写equals方法时,通常也需要重写hashCode方法。这是因为:

  1. 一致性:如果两个对象相等(即equals方法返回true),那么它们的哈希码(hashCode)也应该相等。这是哈希表(如HashMap、HashSet等)的基本要求,以确保哈希表的正确性和性能。

  2. 提高哈希表的性能:当equals方法被重写后,如果不同时重写hashCode方法,那么哈希表中可能会出现大量哈希冲突,导致哈希表的性能下降。通过同时重写hashCode方法,可以降低哈希冲突的概率,从而提高哈希表的性能。

  3. 遵循Java规范:根据Java的约定,如果一个类重写了equals方法,那么它也应该重写hashCode方法。这样做有助于提高代码的可读性和可维护性。

代码示例 

接下来使用set去重来解释为什么重写equels要重写hashcode

这是没写equels和hashcode的代码

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class Main {


    public static void main(String[] args) {
        Student[] students = new Student[6];
        students[0]=new Student("zhangsan",18,1001);
        students[1]=new Student("lisi",17,1009);
        students[2]=new Student("wangwu",28,1006);
        students[3]=new Student("liuliu",19,1004);
        students[4]=new Student("zhaoqi",15,1005);
        students[5]=new Student("zhaoqi",15,1005);

        Set<Student> set = new HashSet<Student>(Arrays.asList(students));
        for (int i = 0; i < students.length; i++) {
            set.add(students[i]);
        }
        System.out.println(set);
    }

}
class Student {
    String name;
    int age;
    int no;

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

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

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

}

 让我们来看运行结果

可以看出来有两个zhaoqi,set的去重并不能将他去掉 

接下来我们看写了equals方法没写hashcode方法的运行截图 

 可以看出来有两个zhaoqi,set的去重依旧不能将他去掉 

 接下来我们看写了hashcode方法没写equals方法的运行截图 

只重写了hashcode没重写也不能成功去重

最后我们看equals和hashcode都重写的情况

[Student{name='liuliu', age=19, no=1004}, Student{name='wangwu', age=28, no=1006}, Student{name='zhangsan', age=18, no=1001}, Student{name='lisi', age=17, no=1009}, Student{name='zhaoqi', age=15, no=1005}]

最后结果成功去重了 

 重写equals和hashcode示例

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

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

什么是 hashcode(哈希码、散列码)?

想解决这个问题,要先知道什么是hashcode。hashCode是jdk根据对象的地址或者字符串或者数字算出来的 int 类型的数值,

hashcode 在 Object 的方法中源码是这样的:

public native int hashCode();

从源码可以看出,Object 中的 hashCode 调用了一个(native)本地方法,返回了一个 int 类型的整数,当然,这个整数可能是正数也可能是负数。

为什么 equals() 方法要重写?

默认情况下,Java中的 equals() 比较的是对象的引用。

equals 方法在 Object 下的实现源码如下:

public boolean equals(Object obj) {
    return (this == obj);
}


 由此可见,相同的对象使用 equals() 进行比较结果会是 false ,这样就没有了比较的意义,所以要重写 equals 方法。

hashCode() 与 equals() 的关系

来了解一下 hashcode() 和 equals() 的关系:

1. 如果两个对象相等(equals 返回 true),则 hashcode 一定也是相同的

2. 如果两个对象不同(equals 返回 false),那么他们的 hashCode 值可能相同、可能不同

3. 如果两个对象的 hashcode 值相同(哈希冲突),那么它们可能相同、可能不同(equals 返回 true 或者返回 false)

4. 如果两个对象的 hashCode 值不同,那么它们一定不同(equals 返回 false)

equals()hashcode()
true(确定)true
false(确定)true / false
true / falsetrue(确定)
falsefalse(确实)


hashCode() 的默认行为是对堆上的对象产生独特值。如果没有重写hashCode(),则该class的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)。
 

重写equals方法为什么还要重写hashcode方法?

回归根本问题:为什么两个方法都要重写。这种情况通常发生在 set 集合去重,我们都知道 set 集合是用来保存不同对象的集合,也就是说 set 集合内没有重复的元素。但有时,set集合会出现“异常”,即没有进行去重操作。

原因就是:只重写了 equals 方法,但没有重写 hashCode 方法。具体分析一下,只重写equals方法,那么 set 进行去重操作时,先判断的是两个对象的 hashcode 是否相等,由于没有重写hashcode() 方法,所以执行的是 Object 类下的hashcode() 方法,此时比较的实际上是两个相同对象的不同引用地址,所以结果出现了 false ,导致 equals 方法不用执行下去,也返回了 false 结果,最后结论就变成了两个明明相同的对象比较的结果是不同的,于是set集合中就插入了两个相同的对象。
 

总结 

  • equals() 方法用于比较两个对象是否相等,而 hashCode() 方法用于获取对象的哈希码

  • 在 Java 中,如果两个对象通过 equals() 方法判断为相等,则它们的 hashCode() 方法必须返回相同的值。这是因为在使用哈希表(如 HashMap、HashSet)等数据结构时,会先根据对象的哈希码确定存储位置,然后再使用 equals() 方法进行比较来确保唯一性。

  • 如果重写了 equals() 方法但没有重写 hashCode() 方法,那么可能会导致以下问题:

    • 当将对象放入哈希表中时,由于 hashCode() 返回的不是相同的值,哈希表无法正确定位到该对象所在的位置,从而无法正常操作该对象。

    • 当使用哈希集合(如 HashSet)时,由于 hashCode() 返回的不是相同的值,哈希集合无法正确判断两个对象是否相等,从而可能导致重复元素的存在。

  • 因此,在重写 equals() 方法时,必须同时重写 hashCode() 方法,以保证对象的相等性和哈希码的一致性

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/325251.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Oracle AWR报告的生成和解读

Oracle AWR报告的生成和解读 一、AWR报告概念及原理 Oracle10g以后&#xff0c;Oracle提供了一个性能检测的工具&#xff1a;AWR&#xff08;Automatic Workload Repository 自动工作负载库&#xff09;这个工具可以自动采集Oracle运行中的负载信息&#xff0c;并生成与性能相…

Python 网络编程之TCP详细讲解

【一】传输层 【1】概念 传输层是OSI五层模型中的第四层&#xff0c;负责在网络中的两个端系统之间提供数据传输服务主要协议包括**TCP&#xff08;传输控制协议&#xff09;和UDP&#xff08;用户数据报协议&#xff09;** 【2】功能 **端到端通信&#xff1a;**传输层负责…

【点云、图像】学习中 常见的数学知识及其中的关系与python实操[更新中]

文章目录 前言一、平均值、方差、协方差平均值&#xff08;mean&#xff09;np.mean()方差&#xff08;variance&#xff09;np.var()总体方差 np.var(a, ddof0)无偏样本方差np.var(a, ddof1)有偏样本方差标准差&#xff08;standard deviation&#xff09;np.std(a, ddof1)默认…

【原创】docker +宝塔+安装zabbix

Zabbix: Zabbix可以监控各种网络服务、服务器和网络设备&#xff0c;而无需在目标设备上安装客户端。它的强大之处在于自带的Web界面&#xff0c;能够提供实时监控和各种报警功能。方法1&#xff1a; 步骤 创建Docker Compose文件: 首先&#xff0c;你需要创建一个docker-comp…

Elasticsearch Windows部署-ELK技术栈

1、下载Elasticsearch、kibana、logstash 本文不介绍ELK相关原理知识&#xff0c;只记录部署操作过程 下载地址Past Releases of Elastic Stack Software | Elastic 选择同一版本&#xff0c;这里选择是当前最新版本8.11.3 解压放在同目录下&#xff0c;方便后续操作与使用 …

基于Simdroid电子散热模块的电子设备机箱散热设计与优化

一、背景介绍 热设计就是通过合理的散热方式保证良好的热环境&#xff0c;确保电子设备可靠的工作。随着电子技术的迅速发展&#xff0c;电子设备的结构越来越复杂&#xff0c;且越来越趋于小型化&#xff0c;散热问题成为了影响设备可靠性的重要因素。据统计&#xff0c;电子…

三种引入CSS的方式

文章目录 CSS基础知识概述CSS的注释CSS的格式 三种引入CSS的方式内嵌式外链式行内式优先级 CSS基础知识 概述 Cascading Style Sheet 层叠样式表 前端三大基础之一(Html结构 CSS样式 JS动作) 最早由网景公司&#xff08;Netscape&#xff09;提出&#xff0c;在1996年受到w…

【51单片机系列】单片机与PC进行串行通信

一、单片机与PC机串行通信的设计 工业现场的测控系统中&#xff0c;常使用单片机进行监测点的数据采集&#xff0c;然后单片机通过串口与PC通信&#xff0c;把采集的数据串行传送到PC机上&#xff0c;再在PC机上进行数据处理。 PC机配置的都是RS-232标准串口&#xff0c;为D型…

1.15io网络

子网掩码 1.由于对于一个网络下面的主机号还是很庞大&#xff0c;为了进一步划分网络&#xff0c;我们可以将主机号再次进行划分为两部分&#xff0c;分别是网段号和主机号 2.此时就引入的子网掩码的概念 3. 在引入子网掩码后&#xff0c;IP 网络号 子网号 主机号 4.子网…

DataX数据同步(全量)

1. DataX简介 1.1 DataX概述 DataX 是阿里巴巴开源的一个异构数据源离线同步工具&#xff0c;致力于实现包括关系型数据库(MySQL、Oracle等)、HDFS、Hive、ODPS、HBase、FTP等各种异构数据源之间稳定高效的数据同步功能。 源码地址&#xff1a;https://github.com/alibaba/Dat…

第十讲 单片机驱动彩色液晶屏 控制RA8889软件:图像运算

单片机驱动TFT彩色液晶屏系列讲座 目录 第一讲 单片机最小系统STM32F103C6T6通过RA8889驱动彩色液晶屏播放视频 第二讲 单片机最小系统STM32F103C6T6控制RA8889驱动彩色液晶屏硬件框架 第三讲 单片机驱动彩色液晶屏 控制RA8889软件:如何初始化 第四讲 单片机驱动彩色液晶屏 控…

【设计模式之美】重构(三)之解耦方法论:如何通过封装、抽象、模块化、中间层等解耦代码?

文章目录 一. “解耦”概述二. 如何给代码“解耦”&#xff1f;1. 封装与抽象2. 中间层2.1. 引入中间层能**简化模块或类之间的依赖关系**。2.2. 引入中间层可以起到过渡的作用&#xff0c;能够让开发和重构同步进行&#xff0c;不互相干扰。 3. 模块化4. 其他设计思想和原则4.…

[我的Rust库更新]get_local_info 0.2.3

今天收到西安城市开发者社区的文章收录通知&#xff0c;谢谢社区的肯定。 随即发布0.2.3版本&#xff0c;增加峰值算法。 get_local_info是一个获取linux本地信息的Rust三方库&#xff0c;其目标是降低获取本地linux系统信息的难度。支持银河麒麟10、UOS、鸿蒙等国产系统。 项…

力扣hot100 只出现一次的数字 位运算

Problem: 136. 只出现一次的数字 文章目录 思路复杂度Code 思路 复杂度 时间复杂度: O ( n ) O(n) O(n) 空间复杂度: O ( n ) O(n) O(n) Code class Solution {public int singleNumber(int[] nums) {int res 0;for(int x : nums)res ^ x;return res;} }

C#编程-使用反射检索元数据

使用反射检索元数据 术语反射通常用来指镜像。如果您站在镜子面前,镜子会反射出您的所有物理属性,如:您的身高、肤色和身体结构。在C#中也一样,反射被用于反射程序有关的所有信息。C#程序可以利用反射获得类在运行时的信息。 反射在运行时获取类型信息的过程中被使用。提…

C技能树-学习笔记(1-2)C语言概述和数据类型

参考&#xff1a;https://edu.csdn.net/skill/c 1、输出 “Hello, World!” 字符串&#xff0c;请选出错误答案。 2、错误的print函数。 for … in …&#xff1a;是python的语法&#xff0c;C语言的写法是for (;&#x1f609; 3、C标准 没有C19标准。 4、了解C编译管道 …

实战whisper:本地化部署通用语音识别模型

前言 Whisper 是一种通用语音识别模型。它是在大量不同音频数据集上进行训练的&#xff0c;也是一个多任务模型&#xff0c;可以执行多语言语音识别、语音翻译和语言识别。 这里呢&#xff0c;我将给出我的一些代码&#xff0c;来帮助你尽快实现【语音转文字】的服务部署。 以下…

3.3.3 使用集线器的星形拓扑

3.3.3 使用集线器的星形拓扑 集线器的一些特点 3.3.4 以太网的信道利用率 多个站在以太网上同时工作就可能会发生碰撞当发生碰撞时&#xff0c;信道资源实际上是被浪费了。因此&#xff0c;当扣除碰撞所造成的信道损失后&#xff0c;以太网总的信道利用率并不能达到100% 3.…

星图地球——Landsat5_C2_SR_T1数据集

数据简介&#xff1a; Landsat5_C2_SR数据集是经大气校正后的地表反射率数据&#xff0c;属于Collection2的二级数据产品&#xff0c;空间分辨率为30米&#xff0c;基于Landsat生态系统扰动自适应处理系统(LEDAPS)(版本3.4.0)生成。水汽、臭氧、大气高度、气溶胶光学厚度、数字…

github访问不了解决方法

github突然无法访问&#xff0c;解决办法如下&#xff1a; 1、首先通过网址GitHub.com - GitHub: Lets build from here GitHub查看当前github.com对应的IP地址&#xff0c;查到的信息如下图所示 2、修改hosts文件&#xff0c;windows系统下修改 C:\Windows\System32\driver…