0

0

如何在自定义类中重写equals以适配Set_符合自反性与传递性的原则

P粉602998670

P粉602998670

发布时间:2026-02-21 13:10:03

|

639人浏览过

|

来源于php中文网

原创

重写 equals 时必须同时重写 hashcode,且二者须基于相同不可变业务字段;需防御 null、类型、继承问题;测试必须用 hashset 验证去重行为。

如何在自定义类中重写equals以适配set_符合自反性与传递性的原则

重写 equals 时必须同时重写 hashCode

不重写 hashCode 是最常见、最致命的错误。Set(尤其是 HashSet)依赖 hashCode 快速分桶,再用 equals 精确比对;如果两个逻辑相等的对象 hashCode 不同,它们根本不会被拉到同一个桶里,equals 根本没机会被调用——结果就是重复元素无法去重。

实操建议:

  • hashCode 必须基于 equals 中用到的**相同字段**计算,且这些字段在对象存入 Set 后不能被修改(否则哈希桶位置失效)
  • 别手写哈希算法,用 Objects.hash(f1, f2, f3)(Java)或 IDE 自动生成,它已处理 null 和类型差异
  • 如果类有继承关系,且父类已重写 equals/hashCode,子类必须显式调用 super.equals()super.hashCode(),否则自反性直接崩

字段选择决定自反性与传递性的生死线

自反性(a.equals(a) 必为 true)和传递性(a.equals(b) && b.equals(c)a.equals(c))不是靠“写对逻辑”就能保住的,而是被你选进 equals 的字段天然约束着。

常见错误现象:

  • 用可变字段(如 lastAccessTimeretryCount)参与比较 → 同一对象两次调用 equals 可能返回不同结果,违反自反性
  • 用浮点数字段(double price)直接 == 比较 → 0.1 + 0.2 != 0.3,导致 a==b 为 true、b==c 为 true,但 a==c 为 false,破坏传递性
  • 混用不同精度字段(如一个用 BigDecimal 存金额,另一个用 int cents)→ 相同业务值可能算出不同 equals 结果

使用场景:只应选择**业务上定义该对象“身份”的不可变字段**,比如 idskuCodeuserId + resourceId 组合,而不是状态快照。

AMiner
AMiner

AMiner——新一代智能型科技情报挖掘与服务系统,能够为你提供查找论文、理解论文、分析论文、写作论文四位一体一站式服务。

下载

空值、类型、继承三连坑必须手动防御

默认生成的 equals 往往漏掉这三处,运行时抛 NullPointerException 或静默返回 false,让 Set 行为变得不可预测。

实操建议:

  • 开头必须判 if (this == obj) return true; —— 这是自反性的底层保障,也是性能捷径
  • 紧接着判 if (obj == null || getClass() != obj.getClass()) return false; —— 用 getClass() 而非 instanceof,避免子类实例误等于父类实例(否则传递性易破)
  • 所有参与比较的引用字段,必须用 Objects.equals(field1, other.field1),它内部安全处理 null
  • 如果字段是数组,用 Arrays.equals(arr1, arr2);如果是集合,确保其 equals 语义符合你的预期(比如 LinkedHashSetTreeSetequals 行为不同)

测试 Set 行为比单测 equals 更能暴露问题

光跑 equals 单元测试过不了真场景。Set 的去重逻辑是 hashCode + equals 的组合行为,必须用真实容器验证。

实操建议:

  • 构造两个字段完全相同的对象 ab,放进 HashSet,断言 set.size() == 1
  • 构造三个对象:ab 相等,bc 相等,放进 HashSet,断言 set.size() == 1(验证传递性落地效果)
  • 把对象加入 HashSet 后,修改其参与 equals 的字段(如果意外允许),再查 set.contains(modifiedObj) —— 应该返回 false(哈希桶错位),这是你设计的预期,不是 bug

最容易被忽略的是:字段语义一致性。比如一个类用 String name 比较,但数据库里 name 允许大小写混合存储,而业务要求“name 不区分大小写相等”,这时 equals 就得用 String.equalsIgnoreCase,且 hashCode 必须用 name.toLowerCase().hashCode() 对齐——差一个 toLowerCase,Set 就会漏去重。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

810

2023.08.02

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

246

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

826

2024.03.01

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

826

2023.08.22

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

826

2023.08.22

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

826

2023.08.22

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

810

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

578

2024.08.29

pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

928

2026.02.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号