对在使用容器HashSet存放自定义对象时重写其类的hashcode和equals方法的几点认识
创始人
2025-06-01 11:15:47
0

判断是否是相同对象时,hashcode和equals方法的调用顺序

  • 先调用hashcode()方法,再调用equals()方法
  • 如果hashcode()方法得到的哈希值不同,那么两个对象一定不相同,不作后续判断
  • 如果hashcode()方法得到的哈希值相同,那么还得判断equals()方法,根据equals()方法的返回值来具体判断两个对象是否相同
  • 为什么哈希值相同,还得再判断equals方法?
    可以去看一下我写的一般哈希 思想与模板代码 理解一下哈希的实现思路
    可以发现会产生hash冲突的现象,即可能有几个key被存在了相同的hash位置,这时候仅凭借hash值是否相等,不能判断两个对象是否相等,这时候还得根据equals()方法来验证判断下,可以理解为一个双保险。

如果想做一些特殊的去重操作,不同于一般的去重,该怎么有效利用hashcode和equals方法?

这里我给出自己在本科毕业设计中的一个样例。

问题需求

我想在HashSet中存放一个类Comparison,这个类的属性有两个对象se1se2和他们之间的名称相似度NameSimilarity和类别相似度CategorySimilarity

public class Comparison{private SE se1;     //实体1private SE se2;     //实体2private double NameSimilarity;        //名称相似度private double CategorySimilarity;    //类别相似度public Comparison(SE se1, SE se2, double nameSimilarity, double categorySimilarity) {this.se1 = se1;this.se2 = se2;NameSimilarity = nameSimilarity;CategorySimilarity = categorySimilarity;}
}

然后,定义两个Comparison对象怎么才算重复呢?
如果一个Comparison对象拥有实体(se1,se2),另一个Comparison对象拥有(se2,se1)(se1,se2),则这两个Comparison对象被认为是重复的,即交换对象里的两个SE对象的位置仍然算是一个Comparison对象

重写hashcode和equals方法

 @Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Comparison that = (Comparison) o;return Double.compare(that.NameSimilarity, NameSimilarity) == 0 && Double.compare(that.CategorySimilarity, CategorySimilarity) == 0&& ( (se1.equals(that.se1)&&se2.equals(that.se2)) || (se1.equals(that.se2)&&se2.equals(that.se1)) );
}@Overridepublic int hashCode() {return Objects.hash(se1, se2, NameSimilarity, CategorySimilarity);//return Objects.hash(se1) + Objects.hash(se2) + Objects.hash(NameSimilarity, CategorySimilarity);// 让se1和se2的顺序对hash值没有影响就行
}

equals方法中的( (se1.equals(that.se1)&&se2.equals(that.se2)) |(se1.equals(that.se2)&&se2.equals(that.se1)) )描述了上述逻辑。
但是发现这样写,仍然不对,没发发掘交换位置的情况,原来是因为交换位置后,Objects.hash(se1, se2, NameSimilarity, CategorySimilarity);算出来的hashcode完全不一样了,根据前面讲的逻辑,一旦hashcode不一样,就不会再去判断equals方法。

优化

 @Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Comparison that = (Comparison) o;return Double.compare(that.NameSimilarity, NameSimilarity) == 0 && Double.compare(that.CategorySimilarity, CategorySimilarity) == 0&& ( (se1.equals(that.se1)&&se2.equals(that.se2)) || (se1.equals(that.se2)&&se2.equals(that.se1)) );
}@Overridepublic int hashCode() {//return Objects.hash(se1, se2, NameSimilarity, CategorySimilarity);return Objects.hash(se1) + Objects.hash(se2) + Objects.hash(NameSimilarity, CategorySimilarity);// 让se1和se2的顺序对hash值没有影响就行
}
return Objects.hash(se1) + Objects.hash(se2) + Objects.hash(NameSimilarity, CategorySimilarity);

这样写,可以让se1和se2的顺序对hash值没有影响,但也没有影响性能,也没有丧失hashcode的效果。

相关内容

热门资讯

刘高畅火速加入国金证券,老东家... 据新浪证券今日消息,国盛证券计算机首席分析师刘高畅将离职加入国金证券。另有网传截图显示,刘高畅入职后...
同仁堂的“贴牌”之痛,老字号该... 导语:最新声明:全面接管涉事企业,责令总经理李声义辞职,其他相关管理人员全部停职。文/每日财报 南黎...
AI中场时刻③|至少46家科技... 2025年末的IPO市场格外火热。先是摩尔线程、沐曦股份陆续登陆A股,后是智谱、MiniMax冲击港...
转型提速重塑价值,中邮保险获评... 2025年的中国寿险市场,复杂多变。消费回暖促进保费增长,但也面临预定利率下调、“报行合一”等监管政...
圣诞夜遭受近三年最大处罚,重庆... 万亿农商行,在圣诞遭遇近三年来最大处罚。12月25日,国家金融监督管理总局重庆监管局披露的罚单显示,...
搭上商业航天概念,风电紧固件龙... 12月25日,A股风电紧固件龙头飞沃科技(301232)盘中股价创历史新高,最高涨至183.93元/...
两代人的财经期刊《商界》+《商... 探索商业奥秘,解锁成长新视角。来源丨商界杂志(ID:shangjiezz)图片丨AI生成成年人搞钱避...
超3900只个股下跌 2025.12.26本文字数:1430,阅读时长大约2分钟作者 |一财阿驴11:31 A股午盘丨沪指...
海保人寿获评 2025金柿奖·... 做好金融消费者权益保护工作,是践行金融工作政治性、人民性的集中体现,更是推动金融业高质量发展的必然要...
重庆农商行多项违规被罚870万... 金融监管的刚性约束持续彰显,银行业合规经营的底线不容逾越。01近日,重庆农村商业银行股份有限公司(以...