【问题标题】:In Java, should the hashCode of an object ever change? [duplicate]在 Java 中,对象的 hashCode 是否应该改变? [复制]
【发布时间】:2015-12-23 11:16:22
【问题描述】:

似乎许多类(例如HashSet)假定对象的hashCode 不会改变。 documentation 明确了equalshashCode 之间的关系应该是什么。

但是实现hashCode 会在对象的生命周期内发生变化,这是糟糕的设计吗?

【问题讨论】:

  • 在我看来,您的问题背后的真正的问题很简单:您的对象何时应该是不可变的,而据我所知,答案是:只要可行。可变对象总是必要的,但我的理解是,由于可变性会增加复杂性,因此应该尽可能限制它们。

标签: java hashcode


【解决方案1】:

不,当可变对象改变其内部状态时,hashCode 改变是可以的。

但是,一旦对象位于需要常量 hashCode 的位置,应用程序必须确保对象不会发生突变,从而导致 hashCode 发生变化。

【讨论】:

  • 这不是这里的问题。例如,同一个不可变的String 可能具有从一个JVM 运行到另一个不同的哈希码。
  • 是相同的“生命周期”吗?除非我们正在思考一些轮回哲学。
【解决方案2】:

至少需要在应用程序中将 hashCode 冻结在一个关心的集合中。通常,hashCode 会在您构建对象时更改(例如,添加到 ArrayList),然后将其添加到集合中并停止更改。稍后,如果您将其从集合中删除,您可以再次对其进行变异。我会说,将不可变数据结构(ala String 或您自己的类型,一直向下)与依赖于 hashCode 的集合(例如,HashMap 键或 HashSet)一起使用通常是最佳实践。

【讨论】:

  • 顺便说一句,类似的事情发生在类似的对象进入像 HashSet、HashMap、PriorityQueue 等的东西——如果对象的值要改变,那么你应该删除它,改变它状态,然后放回去。否则,它会在结构中的错误位置,并且会破坏。
  • erm 对不起,是指 TreeSet、TreeMap 等 :)
【解决方案3】:

这取决于你所说的“一生”。您的确切链接表明:

只要在同一对象上多次调用它在 Java 应用程序的执行期间,hashCode 方法必须始终返回相同的整数

这意味着无法保证对象的哈希码在应用程序的两次不同运行中保持一致。

但它保证在给定的应用程序运行时,即运行 Java 代码的 JVM 实例,对象的哈希码永远不会改变。

合同确实保证了这一点,但仅此而已。

【讨论】:

  • 我没有投反对票,但引用继续“......提供了没有修改对象上的 equals 比较中使用的信息”。因此,即使在单次运行期间,似乎也不能保证/要求 hashCode 不能改变。
  • @Cinnam 但这是给定的!这不是OP的问题......或者如果是,我完全误解了这个问题
  • 我将 OP 的问题理解为“如果遵守 hashCode()/equals() 关系,对象能否从其 hashCode() 方法返回不同的值?”。我的评论只是你回答的一部分,你说它保证哈希码在单次执行期间永远不会改变。我以为您的意思是即使您相应地更改了equals(),也不允许您更改它。
【解决方案4】:

你在谈论不同的事情。 如果你想使用Hash(Map|Set) - 键应该是不可变的对象。 所以在这种情况下 hashCode 也将是不可变的。 但在常见情况下,hashCode 应该随着对象状态而改变(根据对 hashCode 有意义的字段)。

【讨论】:

    【解决方案5】:

    hashCode 不保证在不同的执行中产生相同的结果。正如 javadocs 指出的那样 -

    只要在 Java 应用程序执行期间对同一个对象多次调用它,hashCode 方法必须始终返回相同的整数,前提是没有修改对象上相等比较中使用的信息。该整数不需要在应用程序的一次执行与同一应用程序的另一次执行之间保持一致。

    这是不常见的,类库中的某些类甚至指定了它们用于计算哈希码的确切公式 - 例如细绳。对于这些类,哈希码总是相同的。但是,虽然大多数 hashCode 实现都提供了稳定的值,但您必须不要依赖它。

    此外,有些人认为hashcode 是对象的唯一句柄。这是错误的并且是反模式。例如,字符串“Aa”和“BB”产生相同的 hashCode:2112。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-05-27
      • 1970-01-01
      • 1970-01-01
      • 2014-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多