为什么重写equals方法时,要求必须重写hashCode方法?
1 equals方法
Object类中默认的实现方式是 : return this == obj 。那就是说,只有this 和 obj引用同一个对象,才会返回true。
而我们往往需要用equals来判断 2个对象是否等价,而非验证他们的唯一性。这样我们在实现自己的类时,就要重写equals.
按照约定,equals要满足以下规则。
- 自反性: x.equals(x) 一定是true
- 对null: x.equals(null) 一定是false
- 对称性: x.equals(y) 和 y.equals(x)结果一致
- 传递性: a 和 b equals , b 和 c equals,那么 a 和 c也一定equals。
- 一致性: 在某个运行时期间,2个对象的状态的改变不会影响equals的决策结果,那么,在这个运行时期间,无论调用多少次equals,都返回相同的结果。
举例:重写equals方法
1 class Test 2 { 3 private int num; 4 private String data; 5 6 public boolean equals(Object obj) 7 { 8 if (this == obj) 9 return true; 10 11 if ((obj == null) || (obj.getClass() != this.getClass())) 12 return false; 13 14 //能执行到这里,说明obj和this同类且非null。 15 Test test = (Test) obj; 16 return num == test.num&& (data == test.data || (data != null && data.equals(test.data))); 17 } 18 19 public int hashCode() 20 { 21 //重写equals,也必须重写hashCode。具体后面介绍。 22 } 23 24 }
2 hashCode方法
这个方法返回对象的散列码,返回值是int类型的散列码。
对象的散列码是为了更好的支持基于哈希机制的Java集合类,例如 Hashtable, HashMap, HashSet 等。
关于hashCode方法,一致的约定是:
- 在某个运行时期间,只要对象的(字段的)变化不会影响equals方法的决策结果,那么,在这个期间,无论调用多少次hashCode,都必须返回同一个散列码。
- 如果2个对象通过equals调用后返回是true,那么这个2个对象的has
- hCode方法也必须返回同样的int型散列码如果2个对象通过equals返回false,他们的hashCode返回的值允许相同。(然而,程序员必须意识到,hashCode返回独一无二的散列码,会让存储这个对象的hashtables更好地工作。)
重写了euqls方法的对象必须同时重写hashCode()方法。
3 为什么必须重写hashCode方法?
在上面的例子中,Test类对象有2个字段,num和data,这2个字段代表了对象的状态,他们也用在equals方法中作为评判的依据。那么, 在hashCode方法中,这2个字段也要参与hash值的运算,作为hash运算的中间参数。这点很关键,这是为了遵守:2个对象equals,那么 hashCode一定相同规则。
也是说,参与equals函数的字段,也必须都参与hashCode 的计算。
4 重写hashCode时注意事项
重写hashCode方法时除了上述一致性约定,还有以下几点需要注意:
(1)返回的hash值是int型的,防止溢出。
(2)不同的对象返回的hash值应该尽量不同。(为了hashMap等集合的效率问题)
(3)《Java编程思想》中提到一种情况
“设计hashCode()时最重要的因素就是:无论何时,对同一个对象调用hashCode()都应该产生同样的值。如果在讲一个对象用put()添加进HashMap时产生一个hashCdoe值,而用get()取出时却产生了另一个hashCode值,那么就无法获取该对象了。所以如果你的hashCode方法依赖于对象中易变的数据,用户就要当心了,因为此数据发生变化时,hashCode()方法就会生成一个不同的散列码”。
举个例子
public class Test {private int num;private String data;public Test(int num,String data){this.num = num;this.data = data;}public void setNum(int num) {this.num = num;}public boolean equals(Object obj){if (this == obj)return true;if ((obj == null) || (obj.getClass() != this.getClass()))return false;Test test = (Test) obj;return num == test.num&& (data == test.data || (data != null && data.equals(test.data)));}public int hashCode(){int hash = 7;hash = 31*hash+num;hash = 31*hash+data.hashCode();return hash;}public static void main(String[] args) {Map<Test,Integer> map = new HashMap<>();Test t1 = new Test(21,"ouym");map.put(t1, 1);t1.setNum(20);System.out.println(map.get(t1));}}
输出值为null,我的天呐,hashMap取不到值了。
不重写equals和hashCode方法的话是不依赖于对象属性的变化的,也就是说这里使用默认的hashCode方法可以取到值。但是我们重写equal方法的初衷是判定name和num属性都相等的Test对象是相等的,而不是说同一个对象的引用才相等,而num=21和num=20明显不想等,所以这里hashCode返回值不同并不违背设计的初衷。注意上面代码的使用陷阱。
来自:https://www.cnblogs.com/lulipro/p/5628750.html
转载于:https://www.cnblogs.com/ouym/p/8963219.html
为什么重写equals方法时,要求必须重写hashCode方法?相关推荐
- hashcode相等的两个对象一定相等吗_为什么重写 equals方法时一定要重写hashCode方法?...
推荐阅读: 一线架构师总结SpringBoot,Cloud,Nginx与Docker,不信你搞不懂 47天洒热血复习,我终于"挤进"了字节跳动(附面经+学习笔记) 五年时间,从蘑菇 ...
- Java重写equals方法时为什么要重写hashCode方法
在我们平时编写Java代码时,重写equals方法时一定要重写hashCode方法,这是为什么呢? 在讨论这个问题前,我们先看下Object类中hashCode方法和equals方法. hashCod ...
- 为什么重写equals方法时一定要重写hashCode方法
在每个类中,在重写equals方法的时侯,一定要重写hashcode方法. 根据Object规范,规范约定: 如果两个对象通过equals方法比较是相等的,那么它们的hashCode方法结果值也是相等 ...
- JavaSE——为什么重写equals的同时一定要重写hashCode?
文章目录: 1.引出话题 2.关于equals方法 3.关于hashCode方法 4.为什么要一起重写这两个方法? 5.总结 1.引出话题 equals 方法和 hashCode 方法是 Object ...
- java方法的调用怎么跳出_JAVA 的一个方法调用另一个方法时,怎么把那个方法里的数据调用出来...
例如:此例子中Calcute()方法调用dispMax()方法时,怎么把curCost的数据调用到publicListgetBidListByName1(Stringname)中来,,,谢谢大家来帮忙 ...
- Java中重写equals()方法时注意点
Java中重写equals()方法时注意点 一直说,重写一个对象的equals()方法时我们必须重写HashCode()方法,但是如果我们不重写呢?会有什么影响呢? 首先看一下,什么情况下我们需要重写 ...
- why在重写equals时还必须重写hashcode方法
首先我们先来看下String类的源码:可以发现String是重写了Object类的equals方法的,并且也重写了hashcode方法 public boolean equals(Object anO ...
- 为什么重写equals时必须重写hashCode方法?
2019独角兽企业重金招聘Python工程师标准>>> 首先我们先来看下String类的源码:可以发现String是重写了Object类的equals方法的,并且也重写了hashco ...
- JAVA中重写equals()方法的同时要重写hashcode()方法
object对象中的 public boolean equals(Object obj),对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true:注意:当此方法 ...
- JAVA中list.contains()方法,要重写equals(),hashcode()方法
今天动力节点java培训机构小编为大家介绍"JAVA中list.contains()方法,要重写equals(),hashcode()方法",希望能够帮助正在学习java的零基础学 ...
最新文章
- 阳光学院计算机科学与技术需要英语四级,给各位想报阳光的朋友一点建议!来自学长的亲身经历!...
- whea uncorrectable error蓝屏_Windows 10再出“不可选”更新:蓝屏、死机比较烦
- Service Broker实现发布-订阅(Publish-Subscribe)框架
- 无线 iphone客户端测试白皮书(二)
- jeecg 如何重新加载当前渲染tab页面
- 从源码角度解释 fragment 坑(一)
- C语言 signal
- [渝粤教育] 西南科技大学 现代制造系统 在线考试复习资料2021版
- AC日记——找最大数序列 openjudge 1.9 10
- UnityWebPlayer使用(1) 单机环境下在WinForm中使用Unity3d
- C语言库函数源码在线,C语言库函数(包括所有函数)
- 五笔打字简明教程(86版)
- 10.29 逻辑回归和交差熵
- 观李永乐老师讲音律有感——《管子·地员》之“三分损益法”的探究
- 《黑客帝国》的宗教启示
- elementui的表单验证踩坑-动态绑定输入框required后只显示英文提示
- modelsim is exiting with code:211 10秒后自动关闭退出
- 【Java】SpringBoot后端格式转换:把Word转成PDF再按页转成图片在前端展示(Linux)
- c语言课后答案上海交通,上海交通大学继续教育学院2012春——程序设计(C)作业1(有答案)...
- RC延时电路的 时间常数 和 延时时间(电压达到时间)和电容充放电时间计算和选取