JAVA基础 & hashCode与equals详解

在了解hashCode与equals方法之前,需要知道:

1、JAVA八种基本数据类型的变量没有equals和hashcode方法,只能应用==进行比较;

2、变量1==变量2,比较的是对象在堆内存中的地址,如果要比较其中的内容的话,就要用equals方法(前提是在自己定义的对象中重写了equals方法,如果没有重写equals方法使用equals比较和==的意义是相同的,都是比较对象存放的地址,因为Object 的equals方法,就是用==来实现的)。

学习hashCode与equals方法之前先来试想一个场景,如果你想查找一个集合中是否包含某个对象,那么程序应该怎么写呢?

通常的做法是逐一取出每个元素与要查找的对象一 一比较,当发现两者进行equals比较结果相等时,则停止查找并返回true,否则,返回false。但是这个做法的一个缺点是在需要进行大量并且快速的对象对比时,如果都用equal()去做显然效率太低。于是有人发明了一种哈希算法来提高从该集合中查找元素的效率,这种方式将集合分成若干个存储区域(可以看成一个个桶),每个对象可以计算出一个哈希码,可以根据哈希码分组,每组分别对应某个存储区域,这样一个对象根据它的哈希码就可以分到不同的存储区域(不同的桶中)。如下图所示:

所以解决方式是,每当需要对比的时候,首先用hashCode()去对比,如果hashCode()不一样,则表示这两个对象肯定不相等(也就是不必再用equal()去再对比了)。如果hashCode()相同,此时再对比他们的equal(),如果equal()也相同,则表示这两个对象是真的相同了,这样既能大大提高了效率也保证了对比的绝对正确性!

实际的使用中,一个对象一般有key和value,可以根据key来计算对象的hashCode。假设现在全部的对象都已经根据自己的hashCode值存储在不同的存储区域中了,那么查找某个对象(根据对象的key来查找),不需要遍历整个集合了,现在只需要计算要查找对象的key的hashCode,然后找到该hashCode对应的存储区域,在该存储区域中来查找就可以了。

这种大量的并且快速的对象对比的使用,一般是在hash容器中,比如HashSet,HashMap,HashTable等。比如HashSet里对象无序且不可重复,当添加对象时,它内部必然要对添加进去的每个对象进行对比,而它的对比规则就是像上面说的那样,首先比较两个对象的hashcode值,如果hashcode值相同,则再通过equals比较,再相同的话才能确定是同一个对象,不添加。否则就可以添加进HashSet。 而HashMap,通过一个object的key来取HashMap的value时,工作方法是,通过传入的Object的hashCode在内存中找地址,当找到这个地址后再通过equals方法来比较这个地址中的内容是否和你原来放进去的一样,如果是,就取出value。

这样一来,对比的效率就很高了。

 

那么hashCode()既然效率这么高为什么还要equal()呢?

       因为hashCode()并不是完全可靠,有时候不同的对象他们生成的hashcode也会一样(生成hash值得公式可能存在的问题),所以hashCode()只能说是大部分时候可靠,并不是绝对可靠,所以可以得出:

1.equal()相等的两个对象他们的hashCode()肯定相等,也就是用equal()对比是绝对可靠的。

2.hashCode()相等的两个对象他们的equal()不一定相等,也就是hashCode()不是绝对可靠的。

 

下面就来看看hashCode和equals的区别和联系。

在研究这个问题之前,首先说明一下JDK对equals(Object obj)和hashCode()这两个方法的定义和规范。

在Java中任何一个对象都具备equals(Object obj)和hashCode()这两个方法,因为他们是在Object类中定义的。 

equals(Object obj)方法用来判断两个对象是否“相同”,如果“相同”则返回true,否则返回false。 

hashCode()方法返回一个int数,在Object类中的默认实现是“将该对象的内部地址转换成一个整数返回”。 

举例说明一下:

两个Man对象,存储内容一致,都没有重写hashcode和equals方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值