我知道当我们覆盖equals()
方法时,我们也需要覆盖hashcode()
以及其他方式。
但我不明白为什么我们必须这样做?
在 Joshua Bloch Book 中明确写出我们必须这样做,因为当我们处理基于散列的集合时,满足 <是至关重要的em> Hashcode合约 我承认,但如果我不处理基于散列的集合怎么办?
为什么还需要它?
答案 0 :(得分:1)
使用
equals
比较对值对象的引用的程序员 方法期望找出它们在逻辑上是否等价,而不是 他们是否引用同一个对象。
调用 hashCode 的哈希函数 应该返回
same
哈希码每一次, 当函数应用于相同或相等的对象时。换句话说,两个 等于对象必须一致地生成相同的哈希码。
Object Class
提供的HashCode的实施并非基于logical equivalency
,
所以现在如果你不会覆盖hashCode
但是覆盖equals
,那么根据你2对象是等于的,因为它们将通过equals()
测试但是根据Java它们不是。
Set
开始允许重复!!! Map#get(key)
不会返回正确的值!! 答案 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哈希码来检查对象的相等性。但是对于书中的例子 - 我们需要不同的方式。
同样等于对象必须产生相同的哈希码,只要它们相等,但是不相等的对象不需要产生不同的哈希码。
如果不使用基于散列的集合,您可以破坏合同,不需要覆盖哈希码方法 - 因为您不会在任何地方使用默认实现,但仍然不建议当你将这些东西放在收藏中时,并且会说你拥有它,因为你将来可能需要它