阅读原文:不同时重写equals和hashCode又怎样!
可能一问到equals和hashCode相关的问题,就会有人讲他们的自反性,对称性,一致性,传递性等几条约定了,
此时我不得不佩服,这么多约定竟然都能记得,但我不知道你是不是真的理解呢。
我只能说只要你不碰到这几个主,你也没什么事的!
为什么不能遇到它们几个呢?
因为它们几个会用到hashCode方法。
他们用hashCode方法来干嘛?
hashCode方法是根据对象的地址生成的一个int整数,默认它和地址一一对应的,如果不重写,那么只有对象地址一样的情况下,哈希值才相等。
equals默认用来比较地址是否相同,但当集合中元素增多时,再使用equals判断,效率是比较低的;而哈希值是可以快速定位到指定的元素的,
所以默认Java就使用哈希值来比较定位,因此有了Object.hashCode的约定。
Set怎么实现存储不重复的元素的?HashMap怎么判断相同的key的?有兴趣可去深入了解一下。
例子小王在「堆」中有两套房产,这两套房产位于不同的地址。现在我想要判断这两套房子是否是同一个主人?
于是我去问Object,而Object告诉我这两套房产不是一个人的!
我:为什么呢?
Object: equals告诉我两套房子离了十万八千里,在不同的地方(地址),当然不是同一个人了。
我:这逻辑……(不符合我们常规的认知啊)
既然这样,那我只能重写equals了!
//注意:这是伪代码,省略了很多 //重写equals,认为身份证相同就是同一个人 @Override public boolean equals(Object obj) { return this.idCard == obj.idCard; }
哈哈,好啦,现在equals终于知道这两个房子是同一人的啦!
然而在房产管理局(HashMap)我得到一个消息:小王只要一套房产!
WTF!我白干了!
房产管理局(HashMap): 不信你看!
HashMap
遇到你真是倒霉了,原来房产管理局(HashMap)使用了hashCode来计算的!想要正确的统计小王的房产只能重写hashCode方法了。
@Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (idCard != null ? idCard.hashCode() : 0); return result; }
此时,他们统计终于对了!!!
总结除非你能保证你重写equals的类不被Set,Map使用,否则你就必须同时重写equals和hashCode。
你能保证吗?如果不想同时重写,你可以这样:
/** * 1.此类应用于Set,Map时,需要使用者重写hashCode,违规者后果自负 * 2.本类不能作为第三方类库供其他项目使用 * @author flyhero * @date 2019-04-03 6:14 PM */ public class User {}
信不信这样写,老大看到后,就say goodbye了!
如何重写equals与hashCode我就不写出常说的那些约定性质了,写了也记不住。说说如何避免违反这些约定:
重写equals通过==判断是否是同一个引用
通过instanceof判断是否是相同类型
把参数转为正确的类型
对比双方各个属性值是否相同
如:
@Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof User)) { return false; } User user = (User) obj; return this.name.equals(user.name) && this.idCard.equals(user.idCard); }重写hashCode
hashCode方法应该为“不相等的对象产生不相等的哈希值”
一般计算是根据你equals中用来比较的属性的hashCode组合计算的,不过目前JDK和一些类库已经给我提供了很好的重写方式,我们可不必去深究其中算法。
方式一
@Override public int hashCode() { return Objects.hash(name, idCard); }
使用了JDK自带Objects提供的静态方法。
方式二
@EqualsAndHashCode public class User {}
使用了lombok类库,直接在类上注解即可。
更多精彩技术文章尽在微信公众号:码上实战
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/77480.html
摘要:它也是用来判断两个对象是否相等,所以也得分不同的情况来说明。什么是的作用是获取哈希码,也称为散列码它返回的一个整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。它定义在的中,这就意味着中的任何类都包含有函数。 前言 万丈高楼平地起,今天的聊点基础而又经常让人忽视的话题,比如==与equals()区别?为何当我们重写完equals()后也要有必要去重写hashcode()呢? .....
摘要:如果我们不重写的方法,那么就会默认调用的方法小王小王我们可以看到以上的运行结果违背了的规定如果返回,那么方法必须返回相同的整数所以我们需要对对象的方法进行重写通过重写让其与对象的属性关联起来,那么就能够达到为,那么的值也相等。 面试官让你说说==和equals()的区别,重写equals必须重写hashcode方法吗 本身特质来说 ==:操作符 equals():方法 适用...
摘要:中,任何未处理的受检查异常强制在子句中声明。运行时多态是面向对象最精髓的东西,要实现运行时多态需要方法重写子类继承父类并重写父类中已 1、简述Java程序编译和运行的过程:答:① Java编译程序将Java源程序翻译为JVM可执行代码--字节码,创建完源文件之后,程序会先被编译成 .class 文件。② 在编译好的java程序得到.class文件后,使用命令java 运行这个 .c...
摘要:中,任何未处理的受检查异常强制在子句中声明。运行时多态是面向对象最精髓的东西,要实现运行时多态需要方法重写子类继承父类并重写父类中已 1、简述Java程序编译和运行的过程:答:① Java编译程序将Java源程序翻译为JVM可执行代码--字节码,创建完源文件之后,程序会先被编译成 .class 文件。② 在编译好的java程序得到.class文件后,使用命令java 运行这个 .c...
摘要:这样做的目的是提高取对象的效率。在单线程情况下效率较高在的多线程情况下,同步操作能保证程序执行的正确性。 突然发现整理了很多笔记,应该放这里做备用 Hashtable和HashMap 主要区别:线程安全性,同步(synchronization),以及速度。 HashMap几乎可以等价于Hashtable,除了HashMap是非synchronized的,并可以接受null。Hashta...
阅读 3402·2021-11-24 09:38
阅读 3189·2021-11-22 09:34
阅读 2098·2021-09-22 16:03
阅读 2349·2019-08-29 18:37
阅读 371·2019-08-29 16:15
阅读 1760·2019-08-26 13:56
阅读 853·2019-08-26 12:21
阅读 2197·2019-08-26 12:15