【问题标题】:Is there any reason for returning constant value from hashCode method?从 hashCode 方法返回常量值有什么原因吗?
【发布时间】:2020-11-28 21:00:44
【问题描述】:

我有一个与 java.lang.Object 中关于 hashCode 方法的广泛讨论主题相关的问题。只是有什么理由我应该在某些用例中从hashCode() 返回一个常量值吗?

public int hashCode()
{
   return 3;
}

如果您找到一些直接回答我的问题的文章或 SO 主题,我将不胜感激。坦率地说,我做不到。

我的想法

来自docs.oracle.com object hashCode()(我知道这里引用了很多次):

如果根据 equals(java.lang.Object) 方法,如果两个对象不相等,则不需要对两个对象中的每一个调用 hashCode 方法都必须产生不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同的整数结果可能会提高哈希表的性能。”

所以理论上hashCode() 可以返回一个常量值。在我的想象和我所读到的内容中,当使用例如HashMap 时,所有对象都将被放置在同一个桶中。例如,假设 1000 个元素将被放置在完全相同的哈希桶中(换句话说,将有 1000 次冲突),并在必须迭代 1000 个元素的错误情况下找到特定的元素。然后它将执行类似于LinkedList 集合(如果我错了请纠正我)。

基于上述,hashCode() 可以返回一个常量值,但它会破坏使用hash... 集合获得的性能。那么在一些特定的例子中这样做有什么意义吗?

编辑: 我发现了一个具有常量hashCode 方法的特定示例 基于 Vlad 的 Mihalcea 文章:How to implement equals and hashCode using JPA entity identifier,(休眠)。 HashCode 在实体状态转换之间有所不同,因此它应该返回常量值。引用文章:

当实体第一次存储在 Set 中时,标识符为空。实体持久化后,标识符被分配给自动生成的值,因此 hashCode 不同。因此,实体在持久化后无法在 Set 中找到。

所以有一个实际的例子,但正如它以性能为代价指出的那样。如果除了实体 id 之外还有业务唯一非空标识符,最好使用它以利用将实体存储在多个 Hash... 存储桶中。

【问题讨论】:

  • 没有。返回一个常量哈希码是一个可怕的想法。不要这样做。
  • @ElliottFrisch 请查看我的编辑,这是一个实体示例。
  • 将 JPA 实体业务密钥用于 equals 和 hashCode 始终是最佳选择。 -- 文章接着描述了各种错误 选择。
  • 在必须迭代 1000 个元素的错误情况下找到特定的元素...实际上,不:由于 java 8,当存储桶大小超过 6 时从链表“树化”到平衡二叉树,因此时间复杂度从 O(n) 下降到 O(log n)
  • 酷我不知道,谢谢分享你的知识

标签: java hibernate jpa hash hashcode


【解决方案1】:

当您知道该类只有很少的唯一实例(理想情况下只有 1 个)时,常量 hashCode 才有意义。

例如在实现algebraic data typesSingleton 设计模式时会出现这种情况。

在代数数据类型中,无参数数据类型的所有实例彼此相等。因此 hashCode 必须为所有实例返回相同的值。

在单例模式中,一个类只有一个实例。因此,hashCode 返回什么值并不重要,它可以返回一个常量。

【讨论】:

    【解决方案2】:

    通常,在覆盖哈希码时,您将永远不会返回静态成员。我以前从未这样做过,但我什至可以想象的唯一可能的用例是单例,您希望运行时只有 1 个未延迟初始化的实例。这有点没用,因为如果您将类设计为使用单例模式,则永远不需要使用 equals/hashcode。

    【讨论】:

    • 实体的hashCode 怎么样(查看我的编辑),显然有一个实际用例而不是潜在的单例模式。
    • @jwpol 在那篇文章中,作者没有正确实现 equals/hashcode 合约,因为实体是可变的。那篇文章不是一个很好的用例示例。
    • 哦,谢谢指出。所以基本上Hash... 不是实体的最佳集合,因为它们总是可变的。
    • 不用担心。在 JPA 的上下文中,是的,您通常不会覆盖 equals/hashcode。我唯一能看到在JPA中用@Entity覆盖equals/hashcode的原因是在插入之前在运行时生成主键并且有效地最终以及不可变的,例如随机生成的UUID .
    猜你喜欢
    • 2012-05-10
    • 2021-05-21
    • 2015-03-07
    • 2016-10-16
    • 2018-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多