两个实例具有相同的哈希码但不相等

13
我正在阅读一篇名为Java理论与实践:散列处理-有效和正确地定义hashCode()和equals()的文章,并引用以下段落:
“定义相等性 Object类有两种方法可以推断对象的标识:equals()和hashCode()。通常,如果你重写其中一个方法,你必须同时重写另一个方法,因为它们之间有重要的关系必须维护。特别是,如果两个对象根据equals()方法是相等的,它们必须具有相同的hashCode()值(尽管反过来通常不成立)。[我加粗了强调部分]”
我的问题与段落的后半部分有关:“尽管反过来通常不成立”。如何可能两个不同的类实例具有相同的hashCode但不相等?

3
简单来说,哈希值是固定长度的。由于无法用唯一的哈希值表示所有可能的千字节字符串,因此可能会出现两个不同的千字节字符串产生相同哈希值的情况。 - Hot Licks
Long.valueOf(0).hashCode() == Long.valueOf(-1).hashCode() - nansen
1
阅读关于哈希函数中的碰撞的内容。 http://preshing.com/20110504/hash-collision-probabilities http://en.wikipedia.org/wiki/Collision_resistance - Yegoshin Maxim
8个回答

17

简单来说,hashcode()是一种通过某个公式生成哈希值的函数,因此可能会存在冲突,即两个不同的值可能会具有相同的哈希码。

如果我仅通过将其模6取余来计算哈希码,则两个不同的值可能具有相同的哈希码。


5

将哈希码视为仅简化检查相等性的工具。如果两个对象相等,则它们肯定具有相同的哈希码。但是,如果两个对象具有相同的哈希码,则它们可能在数学上高度相似但仍然不相同。只是为了理解:想象一下在动物园里比较一只鸭子和一只大象。它们非常不相似,会有不同的抽象哈希码,因此您无需费心比较它们的腿、翅膀等来检查它们是否相同。但是,如果您正在比较一只鸭子和一只天鹅,它们非常相似且具有相同的抽象哈希码,因此现在您需要比较每个动物的非常微小的特征以检查它们是否相等。随着被比较元素之间的极端程度降低,抽象哈希码变得越来越具体。比较鸭子和天鹅的哈希码比比较鸭子和大象的哈希码更具体,比较不同品种的鸭子使哈希码更具体,比较同一品种的两只鸭子的DNA 使哈希码更具体。此答案旨在创造一种理解哈希码概念的心态。阅读完毕后,您必须模糊掉与本答案上下文中的哈希码相关联的理解。


5
你可以将哈希视为一个桶..
如果两个对象相等,则它们将进入同一个桶中(具有相同的哈希码)
但是,如果两个对象进入同一个桶中(具有相同的哈希码),并不意味着它们必须相等
还要注意,即使两个对象不相等,它们仍然可能具有相同的哈希码..显然,这是从以上两点推断出来的..
因此,哈希码只是该桶的哈希值..任意数量的对象可以具有相同的哈希码,这取决于用于计算哈希码的算法..
理想的算法是为不同的对象生成不同的哈希码。所以,理想情况下每个桶都只有1个对象。当然,这是完美的情况,可能不太可能实现..
基于某些属性,一个桶可能包含多个对象..

3

我认为相反的情况实际上是:

如果两个对象在equals()方法中不相等,它们必须具有不同的hashCode()值。

这显然是不成立的,因为在一般情况下生成唯一哈希是不可能的,因为你通常试图将一组值映射到较低基数的哈希码集合中。


@RohitJain 你误解了他的写作意图。他并没有声称两个不同的对象不能具有相同的哈希码。他只是引用了与 OP 引用的相反的内容。 - maba

2
我将用一个例子来解释它。假设字符串的 hashCode() 基于字符串长度。在这种情况下,"foo""bar" 的哈希码是相等的。但是 "foo" 本身并不等于 "bar"
这是因为哈希码实现了一种公式:您可以确定每个对象的哈希码,但无法从哈希码还原对象。可能存在多个具有相同哈希码的对象。

1

你可以定义hashCode()实现始终返回1,例如。这是完全有效的:不同的实例(它们不是equal)可以具有相同的hashCode。但在HashMapsSets或其他类型的集合中查找这些对象的运行时性能将非常差(因为它们都落在内部的同一个桶中——查找性能从O(1)下降到O(n),因为您需要遍历同一桶中的对象列表)。

还要考虑查看Java中的HashMaps工作原理


0
一个对象的哈希码通常比原始对象小得多。这是哈希函数的一个目的。因此,您可以想象,如果您有n个不同的对象(例如类的所有排列),则不可能将它们编码为m个(其中m < n)不同且较小(比原始对象)的唯一代码。

0

让我举个例子:

假设一个字符串的哈希码如下所示:hashCode = 每个字符ASCII码的总和(但我们知道,真正的哈希码更加复杂)

例如:字符串“abc”的哈希码计算如下:49+50+51 = 150

那么字符串“acb”的哈希码就等于:49+51+50 = 150

以此类推。正如您所看到的,有许多字符串的哈希码为150,但它们并不相等。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接