hashcode和equals
来源:互联网 发布:球球大作战刷圣衣软件 编辑:程序博客网 时间:2024/05/16 00:41
在Java中,万物皆对象,所有的对象都继承于Object类,Object类有两个方法equals和hashCode。equals一般用来比较两个对象的内容是否相等,而hashCode一般用来提高容器的查询效率。
equals在没有重写的情况下和==是一样的,对于值类型,比较的是值,对于引用类型则比较的是对象的首地址。
hashCode我们一般很少直接使用,它返回的是一个int值,在HashMap中对对象进行存储时,它会调用hashCode方法来比较两个对象是否相等。查询对象的时候也会调用hashCode以提高查询效率。
一般来说equals方法比较相等,则hashCode一定相等,反过来不一定成立,因为具有相同的hashCode不一定是相同的对象。一个好的hashCode函数应该能做到为不同的对象产生不相等的hash值。
如果我们对equals方法进行重写时,一般强烈建议对hashCode方法重写,以保证相同的对象返回相同的hash值,不同的对象返回不同的hash值。因为我们在使用HashMap、HashSet的时候会使用hashCode和equals来判断存入的是否是同一个对象。如果不重写hashCode,那么会继承Object中的,它返回的是一个对象的地址,对于两个对象,这个地址是永远不会相等。如果hashCode都不相等,就不会再调用equals方法进行比较了。
当从HashSet集合中查找某个对象时,java系统首先会调用对象的hashCode()方法来获得该对象的哈希码,然后根据哈希码找到对应的存储区域,最后取得该存储区域内的每个元素与该对象进行equals方法比较。这样就不用遍历集合中的所有元素就可以得到结论,可见HashSet集合具有很好的对象检索性能。
下面我们通过几个例子,演示一下对象重写或不重写hashCode与equals能否被存入HashSet中:
测试1: MyObject类重写了父类Object中的hashCode和equals方法,如果两个MyObject对象的x y值相等的话,那么他们的hashCode的值就会相等,equals后返回true,测试代码如下:
我们向HashSet中存入了4个对象,打印set集合大小为size:2,为什么为2?因为我们重写了MyObject类的hashCode方法,只要MyObject对象的x,y属性值相等,那么它的hashCode值就是相等的。所以先比较hashCode的值,r1和r2对象的x y属性值不等,那么hashCode就不等,所以r2对象可以放进去。r3对象的x y属性值和r1对象的属性值相同,所以hashCode是相等的,然后再比较r1和r3的equals方法,也是相等,所以r1、r3对象时相等的,所以r3不能放进去。最后一个r1肯定也是放不进去的。
测试2:把MyObject对象的hashCode方法注释,即不重写Object对象的hashCode方法,再运行一下代码
运行结果:size:3
因为hashCode方法没有被重写,使用Object中的hashCode方法返回的是对象的地址,不同的实例对象的hashCode是不同的,所以hashset中可以存入r1,r2,r3
测试3:把MyObject对象中的equals方法注释掉,直接返回false,不注释hashCode方法,运行一下代码:
运行结果:size:3
这个结果让人比较意外,首先r1和r2对象比较hashCode不相等,那么r2放入hashset中。再来看一下r3,比较r1和r3的hashCode方法,是相等的,然后比较他们的equals方法,因为equals始终返回false,所以r1和r3也是不相等的,所以r3可以放入set。再看最后一个r1(为防混淆,我们称它为r4吧),r1和r4 hashCode相等,再比较equals返回false,所以r1和r4不相等,同理r2和r4,r3和r4也不相等,所以r4应该可以放入集合中,那为什么集合的大小是3呢?
我们有必要翻一下HashSet的源码了:
我们会发现HashSet是基于HashMap实现的,我们打开HashMap的put方法:
我们主要看一下if中的判断:
if(e.hash == hash && ((k = e.key) == key || key.equals(k)))
首先是判断hashCode是否相等,不相等的话,直接跳过,相等的话,再来比较这两个对象是否相等或者这两个对象的equals方法,因为进行的是“ 或 ” 操作,所以只要有一个成立即可,那这里我们就可以解释了,其实上面的那个集合的大小是3, 因为最后的一个r1没有放进去,因为(k = e.key) == key 即 r1==r1返回true就return了,所以没有放进去了。集合的大小是3,如果我们将hashCode方法设置成始终返回false的话,这个集合就是4了。
- equals() 和 hashCode()
- hashcode()和equals()方法
- hashcode() 和 equals()方法
- 关于equals和hashCode
- 重写equals()和hashCode()
- 关于hashcode()和equals()
- hashcode和equals
- equals和hashCode
- equals 和 hashcode
- 关于equals() 和hashcode()
- 关于equals() 和hashcode()
- equals()和hashCode()
- equals() 和hashcode()详解
- hashCode()和equals()
- equals和 hashcode比较
- 浅谈equals和hashcode
- equals和hashCode方法
- hashCode() 和 equals() 理解
- R语言抓取暴风魔镜评论数据并绘制各省市购买量热力图
- 声明两个变量:int n1=10,n2=20;要求将两个变量交换,最后输出n1为20,n2为10。扩展(*):不使用第三个变量如何交换?
- LCD12864的详解
- 1390 Prepared statement contains too many placeholders
- iOS直播APP-点赞动画的实现
- hashcode和equals
- 23种设计模式 第三部分 关系模式(6)命令模式
- 待解决问题
- [QT起航] 第一篇:环境准备
- HDU1559 最大子矩阵(二维树状数组)
- mongo,mongod双击闪屏的问题
- 1.Android进阶:操作设备管理器
- 数据结构实验之栈二:一般算术表达式转换成后缀式
- 【神经网络与深度学习】【C/C++】使用blas做矩阵乘法