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

news2024/9/22 3:00:21

关于equals与hashCode关系的描述

我们可以先来看一下这个定理

(1)如果两个对象的 hashCode 相等的情况下,对象的内容值不一定相等(hash碰撞问题)

(2)如果使用 equals 方法比较两个对象内容值相等的情况下,则两个对象的hashCode值一定要相等

相信有看过类似文章的小伙伴都可以回忆起一些什么来! 

我们可以用代码的形式来解释上述问题

public class Demo {
    public static void main(String[] args) {
        String a1 = "a";
        Integer a2 = 97;
        System.out.println(a1.hashCode());  //97
        System.out.println(a2.hashCode());  //97
        //false
        System.out.println(a1.equals(a2));
    }
}

可以看出 a1 和 a2 的hashCode值是一样的;但是,使用equals比较内容值是不一样的!就也就印证了定理的第一个小点

这也是发生Hash碰撞的原因!!!

再看看下面的例子

public class Demo {
    public static void main(String[] args) {
        UserEntity user1 = new UserEntity("Harmony", 1234);
        UserEntity user2 = new UserEntity("Harmony", 1234);

        System.out.println(user1 == user2);        // false
        System.out.println(user1.equals(user2));   // false
        System.out.println(user1.hashCode());      // 1163157884
        System.out.println(user2.hashCode());      // 1956725890
    }
}

这里使用 “==” 来判断对象,结果一定是false,因为user1和user2不是同一个对象,它们的内存地址是不同,使用 “==” 比较的就是内存地址!!!

为什么我们两个对象里面的内容值是一样的,而equals值却不相等呢??? 

判断equals() 的结果是false,两个hashCode的也是不相同的!

我们可以按住ctrl然后点击上面的equals()hashCode()方法跟进看一下,发现它们都是调用Object类的方法,如下

// Object 类
public native int hashCode();

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

第一个样例代码,跟进看发现,它们是调String类和Integer类hashCode()equals() 方法,显然在String类和Integer类中对这两个方法做了重写!!!

已String类为例 

// hashCode
public int hashCode() {
    int h = hash;
    if (h == 0 && value.length > 0) {
        char val[] = value;

        for (int i = 0; i < value.length; i++) {
            h = 31 * h + val[i];
        }
        hash = h;
    }
    return h;
}

// equals
public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

显然,这样子就很好解释了。这是因为我们没有对自己创建的UserEntity对象重写equals()和hashCode()方法!!!

UserEntity类 

public class UserEntity {

    private String userName;
    private Integer userId;

    public UserEntity(String userName, Integer userId) {
        this.userName = userName;
        this.userId = userId;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        UserEntity user = (UserEntity) obj;
        return user.userName.equals(userName) && user.userId.equals(userId);
    }

    @Override
    public int hashCode() {
        return userName.hashCode() + userId.hashCode();
    }
}

重新运行,结果如下: 

为什么要一起重写?

(1)Set 正常使用

Set 集合是用来保存不同对象的,相同的对象就会被 Set 合并,最终留下一份独一无二的数据。​

Set 集合最大的特点:去重

但是当我们的Set集合里面存的是自定义对象呢?比如上述的UserEntity

Set<UserEntity> set = new HashSet<>();

显然,这样子让set失去了意义,在HashSet底层也是用hashCode判断是否是同一个元素! 

阿里巴巴Java开发手册 —— equals与hashCode问题

在阿里巴巴的Java开发手册中提到了如果我们要重写 equals 方法,就一定要把hashCode方法也一起重写了!!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

世界杯“引爆”东南亚电商狂潮,电商人如何选品和营销?

世界杯&#xff0c;作为最受关注的国际赛事之一&#xff0c;2022年的世界杯已经在卡塔尔拉开帷幕&#xff0c;中国元素无处不在&#xff0c;为跨境电商行业带来很多新机遇。对于跨境电商来说&#xff0c;更是要牢牢抓住这场全球赛事的商机&#xff01;那么跨境电商人应该如何紧…

全面焕新|详解 Grafana v9.0.x 新增功能特性

Grafana 9.0 是一个提升 Grafana 易用性的版本&#xff0c;通过全新的和改进的操作界面来获取数据&#xff0c;以及默认的 Grafana 警报体验。 Grafana 的一个主要使命是让可观测性、数据可视化和分析更容易的惠及到每个人。对于像 Prometheus 和 Loki 这样的流行数据源&#…

基于Jeecgboot前后端分离的ERP系统开发代码生成(四)

今天主要做一个采购入库单的功能 这个是主从表&#xff0c;所以也是通过online表单设计完成基本功能 1、采购入库单 按照上面生成代码&#xff0c;基本的录入编辑等功能就可以了&#xff0c;当然一些细节需要后续完善 选择商品 2、审核通过 对于库存的更新&#xff0c;需要进行…

跨境电商独立站站群模式

首先我们来了解一下什么是独立站组模式&#xff1f;独立站群模式是指通过建站工具快速建立多个网站。每个网站都有独立的域名&#xff0c;每个网站只存放某个垂直领域的产品&#xff0c;包装成专业的工厂和卖家。每个网站的产品详情和公司实力展示尽量完美(不是市面上的复制品)…

Spring——IOC容器启动及Bean生成流程

IOC容器启动及Bean生成流程一、容器启动IOC启动流程重点二、扫描并注册BeanDefination加载并过滤资源注册BeanDefination三、BeanFactory后置处理四、注册Bean后置处理器五、遍历BeanDefination&#xff0c;实例化单例BeanpreInstantiateSingletonsdoGetBean&#xff08;我们只…

idea配置tomcat,解决控制台乱码问题

问题描述&#xff1a; 配置tomcat&#xff0c;解决idea运行tomcat8.5.27版本控制台输出乱码。 版本&#xff1a; jdk1.8.0_172 IntelliJ IDEA 2019.3 3 (Ultimate Edition) apache-tomcat-8.5.27 解决步骤&#xff1a; 1、打开目录 apache-tomcat-8.5.27\conf\ 目录下 logging…

编译原理—运行环境、局部存储分配、活动记录、全局栈式存储分配、非局部名字的访问、参数传递

编译原理—运行环境、局部存储分配、全局栈式存储分配、非局部名字的访问、参数传递#pic_center 65%x55%1. 运行环境1.1存储组织与分配1.2运行时内存划分2.活动记录2.1活动记录的内容2.2活动记录内容的存取3.静态存储分配3.1FORTRAN静态存储分配4. 动态存储分配4.1 栈式分配下的…

Java反射(Reflex)机制

反射概述 Reflection(反射)是Java被视为动态语言的关键&#xff0c;反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息&#xff0c;并能直接操作任意对象的内部属性及方法。 加载完类之后&#xff0c;在堆内存的方法区中就产生了一个Class类型的对象&#x…

【linux】linux实操篇之软件包管理

前言 关于这一快软件包管理知识点不多&#xff0c;我们主要认识一下rpm和yum这两个软件包管理工具&#xff0c;主要还是yum的使用&#xff01; rpm 包的管理 一种用于互联网下载包的打包及安装工具&#xff0c;它包含在某些 Linux 分发版中。它生成具有 .rpm 扩展名的文件。…

QQ plot 的解读

QQ plot全称是Quantile-Quantile Plot&#xff0c;分位数-分位数图是通过比较两个概率分布的分位数对这两个概率分布进行比较的概率图方法。 这个图形的形式非常简单&#xff0c;有点类似RNA-seq中评价两个样本相关性的散点图&#xff08;图1&#xff09;。这类图形为什么那么…

Java小技能:多级菜单排序并返回树结构菜单列表

文章目录 引言I 生成树形结构菜单列表1.1 获取全部菜单1.2 获取一级菜单,递归获取子节点。1.3 实体1.4 DtoII 常见问题2.1 no instance(s) of type variable(s) R exist so that void conforms to R,2.2 集合filter过滤Integer数值为空问题解决方案引言 需求: 服务商角色配置…

面试官:说说你了解的分布式 ID 生成方案

为什么需要分布式 ID 对于单体系统来说&#xff0c;主键 ID 常用主键自动的方式进行设置。这种 ID 生成方法在单体项目是可行的&#xff0c;但是对于分布式系统&#xff0c;分库分表之后就不适应了。比如订单表数据量太大了&#xff0c;分成了多个库&#xff0c;如果还采用数据…

创业可以做什么项目,六个轻资产创业项目推荐

​2022年已经接近尾声了&#xff0c;你有为下一年做好计划嘛&#xff0c;今年并不是平静的一年&#xff0c;口罩总是反反复复的出现&#xff0c;很多人萌生了创业的想法&#xff0c;那有没有不怕口罩的创业项目呢&#xff1f;虽然创业并不容易&#xff0c;但当你有了正确的方向…

【优化充电】粒子群算法电动汽车充电动态优化策略【含Matlab源码 2163期】

⛄一、粒子群算法电动汽车充电优化 1 电动汽车充电负荷估算 电动汽车的充电负荷主要与电动汽车起始充电时刻和充电时长相关,而起始充电时刻是由电动汽车用户的到家时间决定的,充电时长主要与电动汽车的行驶里程和充电倍率相关。 目前电动汽车还没有大规模运营, 只能通过统计燃…

笔试强训day1

一、选择题 第一题&#xff1a; 题解&#xff1a;y123返回值为123&#xff0c;是非零数&#xff0c;所以y123总是正确&#xff0c;因此循环条件由x<4控制&#xff0c;答案 为C 第二题&#xff1a; %5表示输出总共占据了五列&#xff0c;%.3表示只取字符串左边三个字符并且…

傻白入门芯片设计,wafer/die/chip/cell(一)

1.wafer&#xff1a; 晶圆&#xff0c;指一整个圆形的晶圆硅片。如果问及CPU的原料是什么&#xff0c;大家都会轻而易举的给出答案—是硅。这是不假&#xff0c;但硅又来自哪里呢&#xff1f;其实就是那些最不起眼的沙子。不过不是随便抓一把沙子就可以做原料的&#xff0c;一定…

HTTP 协议

1 HTTP 协议的介绍 HTTP&#xff08;Hyper Transfer Protocol&#xff09;&#xff1a;超文本传输协议HTTP 协议是基于 TCP/IP 协议的超文本&#xff1a;比普通文本更加强大传输协议&#xff1a;客户端和服务器的通信规则&#xff08;握手规则&#xff09; 注意&#xff1a; J…

【计算机毕业设计】21.二手拍卖系统maven源码

一、系统截图&#xff08;需要演示视频可以私聊&#xff09; 引言 近年来&#xff0c;电子商务发展的愈趋成熟使得人们的消费方式以及消费观念发生巨大改变&#xff0c;网上竞拍的拍卖模式随之发展起来。大学拍卖网旨在为湘大学生提供一个线上拍卖的交易平台。平台展示的商品大…

STM32CubeMX时钟树(72MHZ主频配置)

目录 一些基础概念 时钟树配置图 第一步 第二步 这里我只是配置常用的72MHZ主频&#xff0c;很多时候新手都在时钟树这里被劝退了。其实不知道没关系&#xff0c;我用STM32这么久了&#xff0c;也只知道大概。我们绝大多数时候不需要配置这个时钟&#xff0c;记住72MHZ主频…

LeetCode-795-区间子数组个数

1、双指针 根据题意&#xff0c;我们可以将数组中的数分为这三类&#xff1a;1、小于leftleftleft的数&#xff1b;2、大于等于leftleftleft且小于等于rightrightright的数&#xff1b;3、大于rightrightright的数。因此若我们使用双指针来维护区间[last2,last1][last2,last1]…