“定义相等性 Object类有两种方法可以推断对象的标识:equals()和hashCode()。通常,如果你重写其中一个方法,你必须同时重写另一个方法,因为它们之间有重要的关系必须维护。特别是,如果两个对象根据equals()方法是相等的,它们必须具有相同的hashCode()值(尽管反过来通常不成立)。[我加粗了强调部分]”
我的问题与段落的后半部分有关:“尽管反过来通常不成立”。如何可能两个不同的类实例具有相同的hashCode但不相等?
简单来说,hashcode()是一种通过某个公式生成哈希值的函数,因此可能会存在冲突,即两个不同的值可能会具有相同的哈希码。
如果我仅通过将其模6取余来计算哈希码,则两个不同的值可能具有相同的哈希码。
将哈希码视为仅简化检查相等性的工具。如果两个对象相等,则它们肯定具有相同的哈希码。但是,如果两个对象具有相同的哈希码,则它们可能在数学上高度相似但仍然不相同。只是为了理解:想象一下在动物园里比较一只鸭子和一只大象。它们非常不相似,会有不同的抽象哈希码,因此您无需费心比较它们的腿、翅膀等来检查它们是否相同。但是,如果您正在比较一只鸭子和一只天鹅,它们非常相似且具有相同的抽象哈希码,因此现在您需要比较每个动物的非常微小的特征以检查它们是否相等。随着被比较元素之间的极端程度降低,抽象哈希码变得越来越具体。比较鸭子和天鹅的哈希码比比较鸭子和大象的哈希码更具体,比较不同品种的鸭子使哈希码更具体,比较同一品种的两只鸭子的DNA 使哈希码更具体。此答案旨在创造一种理解哈希码概念的心态。阅读完毕后,您必须模糊掉与本答案上下文中的哈希码相关联的理解。
我认为相反的情况实际上是:
如果两个对象在equals()方法中不相等,它们必须具有不同的hashCode()值。
这显然是不成立的,因为在一般情况下生成唯一哈希是不可能的,因为你通常试图将一组值映射到较低基数的哈希码集合中。
hashCode()
基于字符串长度。在这种情况下,"foo"
和 "bar"
的哈希码是相等的。但是 "foo"
本身并不等于 "bar"
。你可以定义hashCode()
实现始终返回1
,例如。这是完全有效的:不同的实例(它们不是equal
)可以具有相同的hashCode
。但在HashMaps
、Sets
或其他类型的集合中查找这些对象的运行时性能将非常差(因为它们都落在内部的同一个桶中——查找性能从O(1)
下降到O(n)
,因为您需要遍历同一桶中的对象列表)。
还要考虑查看Java中的HashMaps工作原理。
让我举个例子:
假设一个字符串的哈希码如下所示:hashCode = 每个字符ASCII码的总和(但我们知道,真正的哈希码更加复杂)
例如:字符串“abc”的哈希码计算如下:49+50+51 = 150
那么字符串“acb”的哈希码就等于:49+51+50 = 150
以此类推。正如您所看到的,有许多字符串的哈希码为150,但它们并不相等。