Hashcode和equals方法契约

时间:2015-03-20 04:48:13

标签: java equals hashcode

我知道当我们覆盖equals()方法时,我们也需要覆盖hashcode()以及其他方式。

但我不明白为什么我们必须这样做?

Joshua Bloch Book 中明确写出我们必须这样做,因为当我们处理基于散列的集合时,满足 <是至关重要的em> Hashcode合约 我承认,但如果我不处理基于散列的集合怎么办?

为什么还需要它?

5 个答案:

答案 0 :(得分:1)

为什么要覆盖等于?

  

使用equals比较对值对象的引用的程序员   方法期望找出它们在逻辑上是否等价,而不是   他们是否引用同一个对象。

现在来到HashCode

  调用 hashCode

哈希函数 应该返回same哈希码每一次,   当函数应用于相同或相等的对象时。换句话说,两个   等于对象必须一致地生成相同的哈希码。

Object Class提供的HashCode的实施并非基于logical equivalency

所以现在如果你不会覆盖hashCode但是覆盖equals,那么根据你2对象是等于的,因为它们将通过equals()测试但是根据Java它们不是。

后果:

  1. Set开始允许重复!!!
  2. Map#get(key)不会返回正确的值!!
  3. 等许多其他因素..................

答案 1 :(得分:0)

因为这就是它的意思:

  

每当a.equals(b),a.hashCode()必须与b.hashCode()相同。

What issues should be considered when overriding equals and hashCode in Java?

有些用例你不需要hashcode(),大部分都是自编的,但是你永远无法确定,因为如果它们是hashcode(),那么实现可能也可能依赖equals()使用{{1}}

答案 2 :(得分:0)

数据结构,例如HashMap,取决于合同。

HashMap通过使用哈希码对条目进行bucketize来实现神奇的性能属性。放在地图中具有相同hashcode()值的每个项目都放在同一个存储桶中。这些&#34;碰撞&#34;通过使用equals()在同一个桶中进行比较来解决。换句话说,哈希码用于确定地图中可能相等的项目子集,并以这种方式快速消除绝大多数项目的进一步考虑。

仅当相同的对象放在同一个存储桶中时才有效,只有当它们具有相同的哈希码时才能确保。

注意:实际上,冲突的数量远远高于上面可能隐含的数量,因为使用的桶数必然远小于可能的哈希码值的数量。

答案 3 :(得分:0)

根据Joshua Bloch的书;

  

常见的错误来源是无法覆盖hashCode   方法。您必须覆盖覆盖的每个类中的hashCode   等于。如果不这样做将导致违反将军   Object.hashCode的合同,它将阻止你的类   与所有基于散列的集合一起正常运行,   包括HashMap,HashSet和Hashtable。

在覆盖equals时未能覆盖哈希码违反了Object.hashCode的合同。但是,如果仅在非基于散列的集合上使用对象,则不会产生影响。

但是,你怎么防止;其他开发商这样做。此外,如果某个对象符合收集元素的条件,那么最好为所有集合提供支持,而不要在项目中使用半烘焙对象。这将在将来的任何时候失败,并且在实施时会因为没有关注联系人而被抓住:)

答案 4 :(得分:0)

这个问题在SO中被多次回答,但我仍然会尝试回答这个问题。

为了完全理解这个概念,我们需要了解哈希码的目的,等于如何实现,以及这个契约到底是什么(当覆盖equals时,也应覆盖该哈希码)

equals 方法用于确定对象的相等性。对于原始类型,它很容易确定相等。我们可以很容易地说int 1总是等于1.但是这个相等的方法讨论了对象的相等性。对象相等性取决于实例变量或任何其他参数(完全取决于实现 - 您想要比较的方式)。

如果我们想要一些定制的比较,这个平等的方法需要被覆盖,假设我们想要说两本书是相同的,如果他们有相同的标题和同一作者,或者我可以说两本书是相同的,如果他们有相同的ISBN 。

hashcode 方法返回对象的哈希码值。 Object hashcode的默认实现为不同的对象返回不同的整数。此整数基于对象的内存地址计算。

所以我们可以说equals方法的默认实现只是comapres哈希码来检查对象的相等性。但是对于书中的例子 - 我们需要不同的方式。

同样等于对象必须产生相同的哈希码,只要它们相等,但是不相等的对象不需要产生不同的哈希码

如果不使用基于散列的集合,您可以破坏合同,不需要覆盖哈希码方法 - 因为您不会在任何地方使用默认实现,但仍然不建议当你将这些东西放在收藏中时,并且会说你拥有它,因为你将来可能需要它