当前位置: 首页 > news >正文

走心解答hashCode与equals,尽量说明白

首先说结论:通过 共同使用hashcode和equals方法 来判断两个对象是否相等。

首先明确:在实际情况下,比较两个对象是否相等,我们关注的是每个对象的属性值是否都相同。

所以在比较前先要重写hashcode和equals方法。

那为什么要重写它们呢?

  • 为什么重写hashcode:因为hashcode默认是Object中的方法,默认比较的是对象的地址值(即使new出来的两个对象属性值都一样,按理说两个对象是相等的,但new出的对象之间的地址不一样),所以我们需要通过在javabean中重写hashcode方法来让其根据对象的属性值去计算对应的hashcode。
    [需要注意的是:重写过hashcode方法并不代表万事大吉不会出现问题,由于哈希冲突的存在导致,实际工作中还要结合equals去判断对象是否相等,下面会有具体解释。也可以联系集合中哈希表存储元素的过程。]
  • 为什么重写equals:而equals默认也是Object中的方法,底层使用“==”去比较对象。对于“==”我们知道:如果是基本数据类型比较的是值是否相等;如果是非基本数据类型(即引用类型)比较的是地址值是否相同。而我们在实际情况(/实际开发)中,需要比较的对象往往是引用类型的,所以需要重写equals方法去比较每个对象的各个属性值是否相同。[需要注意的是:一些包装类型和String类等,都对equals方法进行了重写,它们比较的是对象的值是否相等]

为什么要同时使用 重写后的hashcode重写后的equals 方法 共同去判断两个对象是否相等呢?

  • 如果只使用重写后的hashcode
    •         即使已经重写过,两个属性值不一样的对象,它们的hashcode也可能是一样的(哈希碰撞/哈希冲突)。【实际两个对象并不一样,所以不能只使用hashcode方法去判断 两个对象是否相等】
// eg:
String s1 = "通话";// 两个值不同的字符数组对象
String s2 = "重地";
System.out.println(s1.hashCode() == s2.hashCode());// 用重写后的hashCode去比较的结果竟然是trueString s3 = "abc";
String s4 = "acD";
System.out.println(s3.hashCode() == s4.hashCode());// trueString s5 = "3C";
String s6 = "2b";
System.out.println(s5.hashCode() == s6.hashCode());// true
  • 如果只使用重写后的equals
    •         如果不需要向底层结构是哈希表的集合中存储,只是简单比较,那么只用重写后的equals去比较两个对象是否相等完全ok。【理论可行,但实际还是建议搭配重写后的hashcode方法使用】
    •         但是,但是,如果要向底层结构是哈希表的集合中存储,就必须配合使用重写后的hashcode方法。为什么呢?因为不重写hashcode,在向底层结构是哈希表的集合中存储时,默认会去调用Object中原始的hashcode方法,虽然两个属性值一样的对象我们认为它们是相等的,但计算后得出的hashcode却不一样,按照java该系列集合的底层逻辑,这两个对象会被存储在数组的不同位置,相当于两个一样的对象存储了两次。这显然与java该系列集合的设计思想不符:对于hashset而言,不允许有重复的元素;对于hashmap而言,不允许同一个key对应多个value。

所以我们得出结论:比较两个对象是否相等,需要同时重写equals方法和hashcode方法

hashcode/哈希值/哈希码/散列码

1、2、3、4

👍👍👍

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Windows图形界面(GUI)-MFC-C/C++ - 树形视图(Tree Control) - CTreeCtrl
  • 超声波眼镜清洗机哪个更好用?四款清洁力强的超声波清洗机推荐
  • 24.8.9.11数据结构|链栈和队列
  • 程序人生-Hello’s P2P
  • vue3引入模块报错:无法找到模块“xxx”的声明文件
  • Java 守护线程练习 (2024.8.12)
  • linux 下 QT5如何编译成32位或64的方法
  • 小白零基础学数学建模系列-Day3-线性回归模型的构建与评估
  • 基于STM32开发的智能农业环境监测系统
  • 看过来!数学建模国赛常见问题汇总
  • 全面介绍`npm`的基本使用
  • ISAM2运行流程
  • Mojo 实现排序功能
  • 编程框架、编程脚手架与编程项目模板
  • docker 部署 sql server
  • 4. 路由到控制器 - Laravel从零开始教程
  • CentOS 7 防火墙操作
  • CoolViewPager:即刻刷新,自定义边缘效果颜色,双向自动循环,内置垂直切换效果,想要的都在这里...
  • css的样式优先级
  • gitlab-ci配置详解(一)
  • IE报vuex requires a Promise polyfill in this browser问题解决
  • IndexedDB
  • Java 实战开发之spring、logback配置及chrome开发神器(六)
  • Python进阶细节
  • Travix是如何部署应用程序到Kubernetes上的
  • 基于web的全景—— Pannellum小试
  • 前端
  • 使用putty远程连接linux
  • 双管齐下,VMware的容器新战略
  • 思否第一天
  • 写代码的正确姿势
  • 异常机制详解
  • 用element的upload组件实现多图片上传和压缩
  • 做一名精致的JavaScripter 01:JavaScript简介
  • FaaS 的简单实践
  • Semaphore
  • 我们雇佣了一只大猴子...
  • !!java web学习笔记(一到五)
  • ![CDATA[ ]] 是什么东东
  • # 数仓建模:如何构建主题宽表模型?
  • #70结构体案例1(导师,学生,成绩)
  • #QT项目实战(天气预报)
  • #我与Java虚拟机的故事#连载16:打开Java世界大门的钥匙
  • (1)bark-ml
  • (android 地图实战开发)3 在地图上显示当前位置和自定义银行位置
  • (ros//EnvironmentVariables)ros环境变量
  • (二)springcloud实战之config配置中心
  • (十五)使用Nexus创建Maven私服
  • (四)Android布局类型(线性布局LinearLayout)
  • (转)linux自定义开机启动服务和chkconfig使用方法
  • .\OBJ\test1.axf: Error: L6230W: Ignoring --entry command. Cannot find argumen 'Reset_Handler'
  • .net core 的缓存方案
  • .NET Core 控制台程序读 appsettings.json 、注依赖、配日志、设 IOptions
  • .NET/C# 异常处理:写一个空的 try 块代码,而把重要代码写到 finally 中(Constrained Execution Regions)
  • .net反混淆脱壳工具de4dot的使用