为什么hashCode()和equals()都存在

3
为什么Java中的Object类有两个方法hashcode()和equals()?它们中的一个看起来是多余的,而且这些方法被传递到了最底层的派生类中?

5
你至少可以尝试阅读API——Object.hashcode()的Javadoc明确表示:“此方法支持Hashtable等哈希表的使用。” - William Billingsley
4个回答

12

你认为为什么 hashCode 是多余的?它们表达的意思是不同的:

  • hashCode 的作用是“提供一种有效的方式来判断两个对象是否可能相等”
  • equals 的作用是“检查这个对象是否与另一个对象真正相等”

你绝对需要这两个方法 - 虽然我不认为它们应该一开始就在 Object 中

你绝对需要哈希码来在哈希表中进行高效查询 - 但你还必须进一步检查相等性,因为哈希码会发生冲突(例如,可能出现更多的字符串比哈希码)。


1
“我不认为它们应该真的在Object类中。” 你是指它们两个,还是只是hashCode()方法?将equals()作为一个最终方法来检查身份(可能以不同的名称命名以避免混淆)似乎对我来说是正确的位置。然而,将equals()作为一个虚拟方法来检查相等性似乎是错误的位置。 - R. Martinho Fernandes
2
@Martinho:两者都可以。引用标识已经可以使用“==”进行检查...但大多数类型实际上并没有“相等”的概念,也没有基于它们的数据的合理哈希 - 那么为什么要将它们广告宣传给所有对象呢?当然,博客文章有更多细节 :) - Jon Skeet

2

首先,当你重写equals()方法时,必须同时重写hashcode()方法。

如果不这样做,将会违反Object.hashCode的通用约定,这将导致你的类与所有基于哈希的集合(包括HashMap、HashSet和Hashtable)不能很好地配合使用。

以下是从Object规范[JavaSE6]中复制的约定:

  • 在应用程序的执行过程中,如果hashCode方法在同一个对象上被多次调用,则只要 equals比较所用的信息没有被修改,它就必须始终如一地返回相同的整数。这个整数不需要在不同的应用程序执行之间保持一致。
  • 如果两个对象根据equals(Object)方法是相等的,则对这两个对象中的每个对象调用hashCode方法都必须产生相同的整数结果。
  • 如果两个对象根据equals(Object)方法是不相等的,则对这两个对象中的任一对象上调用hashCode方法不要求产生不同的整数结果。然而,程序员应该意识到,为不相等的对象生成不同的整数结果可以提高哈希表的性能。

2
基本思路是通过比较哈希码(hashcode())来快速检查两个对象是否可能相等。如果它们的哈希码相等,则这些对象可能相等(不一定,但这是一个很好的猜测)。然后执行更深入(也更昂贵)的equals()检查。 这对于加速各种查找(从映射等)非常重要。

另外,由于hashCode是一个int类型,它可以被用作索引来加速查找,通过作为随机访问的某个东西的索引。 - R. Martinho Fernandes

1

在编程中,equals用于比较对象,hashcode用于从对象生成哈希值,然后由Java映射容器(Hashtable、Map等)使用。

通常的做法是同时覆盖它们(如果你重写了hashcode,你需要同时重写equals反之亦然)。


2
@Neeraj:hashCode 可能会发生冲突,即具有相同 hashCode 的对象并不总是相同的。 - R. Martinho Fernandes
这并不是为了那个。两个完全不同的对象可以具有相同的哈希码。想象一下,哈希码的最大值为Integer.MAX_VALUE,而理论上您可以创建无限数量的不同对象。 - BalusC

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