equals和hashCode的关系

8 篇文章 0 订阅
5 篇文章 0 订阅

摘自微信公众号:https://mp.weixin.qq.com/s?__biz=MzU1NTg0MzMwMg==&tempkey=OTk5X2lLRlRkeTM5dThPMmI0cm4xRnBlODRoem9KNnY3MjMzLUN3cDVkazR5TXlrSWhxdzBINHExYlVoT0ItTXQtUy1lejM0djNRcUVWNUpHUkVKcTkwaDhJRE9GWXJHQnRZcVdZcllqc3RHNDF4STluSWl6aGtFNnZvRFN6T0Z2MmozNURaVExSZllvcDNfdHhKUlBPU3RaX3Z5NER5WngwQnBpMTI3dWd%2Bfg%3D%3D&chksm=7bcf6ae24cb8e3f413f63b839b6cbfe151005ad78dcbc8443198a1a3f90bbbfce6269ffe496d#rd

 

之前讲了equals和==之间的关系,今天讲hashCode之间的关系。

什么是hashCode?

我们想一个场景:我们要去除一组数中重复的值,保留不相同的值。

我们首先遍历,然后比较他们如果有相同的就干掉,普通的方式还得循环嵌套。如果把这组数换成一组对象的话,我们又如何去掉相同对象,内容相同的只保留一个呢。如果我们按照之前的方法,就得遍历数组,然后用get方法获取对象中的值,依次比较。这种方式不仅很蠢而且很慢,我们能不能像比较数字那样去比较对象呢?只要我们保证内容相同的对象生成相同的整数就好了,这样就好比较了,这个整数就是hashCode。

hashCode会出现冲突,什么叫冲突,就是我们不能保证不同的对象生成的不同的hashCode,有可能不同的对象生成的hashCode是相同的,这时候我们怎么区别呢,那么我们就需要比较对象的所有字段了,就是重写equals方法,在equals方法中去比较两个对象的所有字段。

hashCode的生成方式有很多种,

Object的hashCode是把对象的地址转化成16进制表示,String类中把每个字符的ascall码计算进来

char val[] = value;

for (int i = 0; i < value.length; i++) {

      h = 31 * h + val[i];

}

大家可能会问,我们实现一下equals不是一定能判断对象是不是内容一样的吗?为什么还要去实现hashCode?

因为hashCode判断快啊,而且当一个对象包含很多字段的时候,一个字段一个字段的比较是很耗时间的。能通过所有字段算出一个数字,直接比较这个数字是不是非常快呢?当hashCode不同的时候,一定不相同,当hashCode相同的时候,再去通过equals判断,这样既高效又准确。

比如我们的HashSet类就是这么实现的,大家知道HashSet中不会存在内容相同的元素,保证每个元素的值都是不一样的,经常用来元素去重。这要求我们去实现hashCode和equals两个方法,少实现其中任何一个都不能达到我们预期的效果。它会首先去判断hashCode是否一样,如果不一样,则2个元素都保留,如果hashCode相同,再去通过equals判断。

我们hashCode和equals都不重写的时候,这输出的是2,也就是这两个对象被认为是不一样的。

当我们只重写hashCode的时候,输出的还是2,当比较hashCode的时候,发现是一样的,然后又去比较equals,而这时的equals还是Object的euqals()方法,==来比较的。

所以这时2个对象,地址不一样,那么认为是不同的对象了,都保留了。

当只重写equals的时候,输出的还是2,先获取hashCode,这时是Object的hashCode,依然是地址的16进制,所以是不同的,equals都不用比较。

只有当既重写hashCode又重写equals的时候,输出才是1,这时候才被认为是相同的。首先比较hashCode,重写之后的值是一样的(1的hashCode和11的hashCode的相加),然后比较equals,比较字段还是相等的,这时只保存一个对象,所以长度就是1

一般我们equals和hashCode一起重写的原因就在这

 

摘自微信公众号

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值