一文搞定 equals 和 hashCode
主要是说一下 equals 和 hashcode
HashCode
此方法主要是用来支持 hash tables。比如 HashMap
要求在 equals 不改动的情况下,每次调用得到的 hashCode 必须是一致的。
两个对象 equals 相等,则 hashCode 也应该相等。
equals 不相等,则不必要求 hashCode 一定不同,应尽量不同以保证高性能。
默认实现,通常是通过对象的内部地址转换为整数,所以大多数情况下 Object 定义的 hashCode 确实可以为不同的对象返回不同的整数。
Equals
对于 non-null reference x ,满足 x.equals(x) return true。
对于 non-null reference x,y 满足 对称性 即:如果 x.equals(y) return true ,则 y.equals(x) 也会 return true 。
对于 non-null reference x,y,x 满足 传递性。即:如果 x.equals(y) return true 和 y.equals(z) return true,那么 x.equals(z) 也应该 return true 。
对于任何 non-null reference x,y,满足一致性,x.equals(y) 要是 true永远是true
对于任何 non-null reference x, x.equals(null) return false.
当重写 equals 方法是必须需要重写 hashCode,这样才能保证 equals 为true的两个对象的 hashCode也一样。(jre 中就有违背这条的类存在)
equals 默认是比较的内存地址。所以默认情况下,当 equals 相等的时候,hashCode也是相等的。
什么时候应该覆盖 equals
我们知道 equals 默认比较的内存地址,即是否为同一个对象。如果类具有了自己特有的逻辑相等,即属性值等,的概念时,并且超类没有覆盖或者覆盖了单不满足子类需求的情况下重写 equals。
但对于类似枚举类这样的 class 而言,每个属性最多只存在一个对象,逻辑相等与内存地址相等时一样的,不需要重写。
为什么要覆盖 equals( hashCode)
结果
这完全不是我们想要的,我们希望的是 map.containsKey(student1) 为true。但为什么是 false 呢?通过源码我们可以知道 应为 equals 不等,导致的。同理,对于 hashCode 也是如此。
任何时候都需要覆盖 equals 和hashCode
答案是 否定的。
还记得上一篇说过的吗,JDK 内部就有违背 equals hashCode 一致性规则的。另外的话,hashCode 仅仅针对 hash 表来说才有用。
结果
对于 list 而言,根本就不需要 比较hashCode,我们也违背了 equals 与 hashCode 的一致性,但对于 students.contains(student1) 结果就是正确的
总结
1.java 集合内部比较对象是否相等一般用的都是 equals ,所以 equals 是要尽量重写的。
2.而对于 hashCode 来说,对于 hash table 来说是必须要重写的,其他的可以不重写。
版权声明: 本文为 InfoQ 作者【shengjk1】的原创文章。
原文链接:【http://xie.infoq.cn/article/1597cc047612823567f126310】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论