【问题标题】:hashCode() value changes between executionshashCode() 值在执行之间发生变化
【发布时间】:2019-08-13 15:09:59
【问题描述】:
对象的

hashCode在应用程序的一次执行过程中必须与该对象保持一致—— 对于任何对象 o,o.hashCode() 应该返回相同的 int 值。

但是,这不一定是从一个运行时到另一个运行时:o.hashCode() 可以返回一些其他值,这对specs 来说完全没问题。

HashMap 根据 hashCode 值计算右降压。

我的问题是:这个值在一个会话到另一个会话之间的变化是如何处理的? 序列化是否具有处理此问题的功能?

所以,假设我构建了一个哈希并将其存储在磁盘上。 2 周后,我调用了应用程序并 运行它。我正在哈希中查找一个对象。通过这些,hashCode 这个对象现在/可以与以前不同 尽管它在散列中,但我将无法找到它。

【问题讨论】:

    标签: java serialization hashcode


    【解决方案1】:

    这是有效的,因为哈希表没有序列化为哈希表。它们以自定义方式序列化。所以当反序列化时,哈希表将使用新的哈希码重建。

    【讨论】:

    • 有/没有办法按原样存储 HashMap 及其整个结构?
    • @Roam 你为什么要这样做?您已经知道不这样做的一个原因 - 运行之间哈希码的可变性。此外,哈希表的组织是为了快速搜索,而不是空间效率。
    • @Roam:你不需要问这个问题。从您的角度来看,您只关心HashMap 是否已恢复。请注意,如果序列化 HashMap 中的所有元素都使用基本的 Object.hashCode() 实现(通常返回对象实例的内存地址),您仍然需要通过其他方式获取哈希映射中的对象列表( values()) 在哈希映射中找到这些对象之前,因为新实例化的对象永远不会与映射中的对象具有相同的哈希码。这就是为什么您通常应该根据业务价值实现自己的hashCode()
    • @PatriciaShanahan 弄清楚我能/不能用它做什么。但我想把它保存在磁盘上没有意义。
    【解决方案2】:

    正如您所说,Object.hashCode() 的一般合同确实指定哈希码可以在运行之间更改。

    但是,如果您需要一个在运行之间改变的哈希码,您只需用您自己的实现覆盖hashCode() 即可保证这一点。

    您的应用程序要求施加了额外的规则,但这些不会违反一般的Object.hashCode() 合同。因此,您可以安全地实现自己的 hashCode() 以满足您的要求,而不会破坏其他任何东西。请注意,hashCode()要求哈希码在运行之间有所不同,它只是允许它。

    顺便说一下,规范允许这样做的原因是因为基本实现只返回对象的内存地址,这在运行之间可能会有所不同。这有时适用于快速的一次性使用,但通常不适用。您通常希望实现一个hashCode(),它根据业务值计算哈希码,这在运行之间是一致的,并且对于业务级别相等的对象也是相同的(即两个具有相同值的Integer 实例)。

    正如 Robin Green 所指出的,Java 的 HashMap 实现了与存储时对象的哈希值无关的自定义序列化。 然而,如果您要实现自己的哈希表,并且只是存储对象的哈希值,您将保证在反序列化哈希表后可以找到对象(当然,除非您只使用一致的hashCode() 在其中存储对象)。

    【讨论】:

      【解决方案3】:

      当您序列化哈希表时,您序列化的是值,而不是哈希码。序列化哈希码是个坏主意。

      【讨论】:

      • 哈希码用于确定哈希桶;它们是计算出来的,不需要存储。事实上,它们不能被哈希表缓存,因为这会导致无限回归的问题——哈希表需要另一个哈希表来查找其中的哈希码。
      猜你喜欢
      • 1970-01-01
      • 2021-02-26
      • 1970-01-01
      • 1970-01-01
      • 2012-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多