[Java]重写equals为什么要重写hashcode???配合HashMap源码一起理解

news2024/11/25 4:22:16

文章目录

  • 1、什么是hashCode
  • 2、为什么要有hashCode
  • 3、为什么重写 equals 时必须重写 hashCode 方法?
  • 4、易错点

1、什么是hashCode

hashCode()是Object定义的方法,它将返回一个整型值,这个方法通常用来将对象的内存地址转换为整数之后返回,它存在的价值是为Hash容器处理数据时提供支持,Hash容器可以根据hashCode定位需要使用的对象,也可以根据hashCode来排除2个不相同的对象,即:hashCode不同,则视为2个对象不同。

2、为什么要有hashCode

哈希码主要在哈希表这类集合映射的时候用到,哈希表存储的是键值对(key-value),它的特点是:能根据“键”快速的映射到对应的“值”。这其中就利⽤到了哈希码。
例如 HashMap 怎么把 key 映射到对应的 value 上呢?用的就是哈希取余法,也就是拿哈希码和存储元素的数组的长度取余,获取 key 对应的 value 所在的下标位置。

3、为什么重写 equals 时必须重写 hashCode 方法?

举例说明:

新建一个User类

public class User {

    private String name;

    private Integer age;

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

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

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

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

上述代码中的equals和hashCode是还没有进行重写的默认原始方法,可以看出,如果没有重写equals方法,那么两个对象进行equals比较时,只有当两个对象的所有属性都相等时,才会认为两个对象相等。

public class Test {
    public static void main(String[] args) {
        User user =new User();
        user.setName("yhz");
        user.setAge(18);

        User user1 = new User();
        user1.setAge(19);
        user1.setName("yhz");

        System.out.println(user.equals(user1));
    }
}

在这里插入图片描述

现在只改一下equals:

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

现在只要两个User对象的name相同,那么就认为这两个User对象相同。
在这里插入图片描述
现在,我new一个HashSet集合,将两个user对象add进去,大家猜猜set里面有几个User

		User user =new User();
        user.setName("yhz");
        user.setAge(18);

        User user1 = new User();
        user1.setAge(19);
        user1.setName("yhz");
			
		System.out.println(user.equals(user1));
		
		Set<User>set= new HashSet();
        set.add(user);
        set.add(user1);
        System.out.println(set);

公布答案:
set里面有两个user对象,欸?上面user.equals(user1)明明返回的是true,我们也知道,Set的特点是不重复,那为什么还会出现两个呢?

原因是: HashSet、HashMap集合在添加元素的时候,用哈希取余法,也就是拿hashCode和存储元素的数组的长度取余,获取 key 对应的 value 所在的下标位置。如果获取到的下标位置上已经存在元素,则认为产生了哈希碰撞(hashCode() 所使用的散列算法也许刚好会让多个对象传回相同的散列值。)再拿新添元素(新的)与当前位置上的元素(旧的)进行equals比较,如果返回true就用新的替换旧的。如果返回false就添加到该位置下面的链表尾或红黑树上。而如果没有发生哈希碰撞,也就间接说明两个对象不相等。然而我们上面只是重写了equals方法(只比较name是否相同),而hashCode返回的还是name和age组合成的数组的hashCode,所以虽然equals返回true,但是两个对象的hashCode不一样,set里存在两个user而不是一个。
HashMap的put过程源码讲解在这里
hashCode() 的默认行为是对堆上的对象产⽣独特值。如果没有重写 hashCode() ,则该 class 的两个对象⽆论如何都不会相等(即使这两个对象指向相同的数据)

现在重写hashCode方法

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

再看一下执行结果:
在这里插入图片描述
这回set里只有一个user了。
所以一定记住,重写 equals 方法时必须重写 hashCode 方法。

好了,到这里希望你已经理解重写equals为什么要重写hashcode了😀

4、易错点

  1. hashCode相等,两个字符串不一定相等。
  2. hashCode相等,这两个对象不一定相等。
  3. hashCode不等,这两个对象一定不相等。
  4. 如果两个对象分别调⽤ equals 方法都返回 true,则这两个对象一定相等。

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

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

相关文章

融云「北极星」数据监控平台:数据可视通晓全局,精准分析定位问题

↑ 点击预约“融云北极星”直播↑ 点击预约“实时社区”直播 近期&#xff0c;融云“北极星”数据系统完成功能迭代&#xff0c;新模块“数据监控平台”正式“履新上任”。关注【融云全球互联网通信云】了解更多 点击图片查看更多详情 此前&#xff0c;“北极星”系统主要为客…

MYSQL中的锁(面试难点重点)

首先说一下 这个加锁是个啥子过程呢 我们拿一条记录举例,这个记录就放在这,没人操作它,他就没生成锁结构, 直到有个事务操作它了,然后给它才生成了个锁结构,锁结构两个参数 trx(生成该锁的事务) is_waiting(正在等待就是:true 没在等待就是 false) (锁里面很多参数 这里这是为…

Linux/Unix-gcc编译回顾

1、gcc编译为可执行程序四步骤&#xff1a;预处理->编译->汇编->链接 注意&#xff1a;-o 用于修改生产的文件名 2、gcc常用参数 指定头文件&#xff1a;-I 语法&#xff1a; gcc -I 头文件所在文件夹路径 源文件 -o 生成文件名 如果头文件和源文件中同一个文件夹…

事务的实现原理

事务的实现 简介特性&#xff08;ACID&#xff09;状态与分类 实现机制日志机制redo logundo log 锁机制 如何使用 简介 有许多小伙伴初学事务还不太清楚是干什么的&#xff0c;那么我们在简介中一次性将事务给搞懂 首先我们先来简单的说一下事务是什么&#xff0c;以便更好的去…

企业数据治理实战总结--数仓面试必备

文章整理自涤生大数据老师宇哥&#xff0c;宇哥是历任中国电信&#xff0c;平安银行&#xff0c;微众银行&#xff0c;众安保险等多家公司擅长大数据求职面试&#xff0c;数仓开发管理&#xff0c;数据治理&#xff0c;数据质量等工作&#xff0c;主导过相关平台的建设 1 数据…

mybatis和dbeaver安装部署连接测试

ORM对象关系映射&#xff0c;把对象和数据库中的数据进行映射。mybatis是orm框架&#xff0c;mybatis-plus是mybatis的增强工具&#xff0c;简化开发。 1.准备mysql数据库 首先安装mysql https://dev.mysql.com/downloads/file/?id518835 设置密码&#xff1a;0000 然后下db…

大数据学习01-Zookeeper分布式集群部署

二、下载 zookeeper官网&#xff0c;本文使用的是zookeeper3.4.8版本 三、安装部署 将下载好的安装包上传至linux服务器上 解压安装包 tar -zxvf zookeeper-3.4.8.tar.gz -C /home/localzookeeper目录重命名 mv zookeeper-3.4.8 zookeeper配置环境 vim /etc/profile添加…

自定义实现list及其功能

#pragma once #include <iostream> #include <assert.h> using namespace std;namespace test {//******************************设置结点******************************template<class T>struct list_node{T _data;list_node<T>* _next;list_node&l…

SQL27 查看不同年龄段的用户明细

selectdevice_id,gender,casewhen age>25 then 25岁及以上when age>20 then 20-24岁when age<20 then 20岁以下else 其他end as age_cut from user_profile

Python property 定义与应用

目录 一、前言二、定义 一、前言 在 Python 类这一节中&#xff0c;会涉及到属性的私有化&#xff0c;私有化的好处在于我们无法轻易地更改类体中属性值&#xff0c;而对于类体中的私有化属性其实也并非真正的私有化&#xff0c;而是一种伪私有化&#xff0c;我们可通过 dir()…

71、redis主从复制的核心原理

redis主从复制的核心原来 通过执行slaveof命令或设置slaveof选项&#xff0c;让一个服务器去复制另一个服务器的数据。主数据库可以进行读写操作&#xff0c;当写操作导致数据变化时会自动将数据同步给从数据库。而从数据库一般是只读的&#xff0c;并接受主数据库同步过来的数…

Android JetPack Compose之主题的理解与使用

目录 概述1.什么是MaterialTheme2.MaterialTheme与CompositionLocal的联系2.1 MaterialTheme的工作原理2.2 CompositionLocal2.3 CompositionLocal的两种创建方式2.3.1 compositionLocalOf2.3.2 staiticCompositionLocalOf 2.4 CompositionLocal总结 概述 根据百度百科知识&am…

Springboot + Vue 上传Word文档并保留内部格式

因为业务需求&#xff0c;上传Word文件需要编辑&#xff0c;但如何使用Blob方式&#xff0c;在数据库里存文件&#xff0c;就会造成格式消失。所以修改思路&#xff1a;上传文件到服务器本地&#xff0c;保证数据存储的完整性。 前端 <el-upload class"upload-demo&quo…

复习PHP基础教程

PHP 安装 PHP 简介PHP 语法 我需要什么&#xff1f; 如需开始使用 PHP&#xff0c;您可以&#xff1a; 使用支持 PHP 和 MySQL 的 web 主机在您的 PC 上安装 web 服务器&#xff0c;然后安装 PHP 和 MySQL。 使用支持 PHP 的 Web 主机 如果您的服务器支持 PHP&#xff0c…

基数排序|RadixSort|C++实现

前言 那么这里博主先安利一些干货满满的专栏了&#xff01; 首先是博主的高质量博客的汇总&#xff0c;这个专栏里面的博客&#xff0c;都是博主最最用心写的一部分&#xff0c;干货满满&#xff0c;希望对大家有帮助。 高质量干货博客汇总https://blog.csdn.net/yu_cblog/c…

电商 api 接口文档

电商 api 接口文档 1、开篇 欢迎使用ShowDoc&#xff01; API格式&#xff1a; 备注&#xff1a;电商API必须返回如下3个字段&#xff1a; 参数名必选类型说明status是int状态message是string信息提示result否mix结果 2、用户相关 2.1、登录/退出 简要描述&#xff1a; …

【复盘】记录一次类型不一致导致的Kafka消费异常问题

背景 业务主要是通过A系统向B系统写入Kafka&#xff0c;然后B系统消费Kafka 将结果写到Kafka中&#xff0c;A进行消费最终结果。 在整个流程中&#xff0c;A写入Kafka会写入一张 record1表记录&#xff0c;然后在A消费最终结果的时候也记录一张record2表。主要改动的话 只是B系…

从Web2到Web3:区块链技术的未来前景

随着互联网的发展&#xff0c;Web1.0、Web2.0 和 Web3.0 成为了人们口中津津乐道的话题。那么&#xff0c;这三种网络时代究竟有什么区别呢&#xff1f; Web1.0 是一个只读的时代&#xff0c;那个时候&#xff0c;用户只能浏览网页&#xff0c;无法进行互动和创作。Web2.0 则是…

什么是社会智商?24种人格力量之社会智商的力量

什么是社会智商&#xff1f; 社会智商指的是将人的智力具体化&#xff0c;自己对他人的了解以及自我剖析能力的高低。一般而言&#xff0c;社会智商越高&#xff0c;对他人的观测能力越高&#xff0c;自我剖析就越透彻。社会智商来源于via 24种人格力量&#xff0c;是人格的优…

FPGA实现UART协议的接收与发送

一、接收模块uart_rx.v UART协议&#xff0c;空闲时&#xff0c;TX和RX数据线都是通过上拉电阻拉高的状态&#xff0c;这样才能在起始位到来时检测到一个下降的边沿。 UART数据格式 uart_rx.v模块输入输出示意图 RX_start。首先&#xff0c;找到起始位的开始时刻RX_start&…