【问题标题】:Does default hashcode change on object mutation对象突变的默认哈希码是否更改
【发布时间】:2012-08-02 04:21:36
【问题描述】:

我知道 hashmap 键应该是不可变对象,或者至少具有一致的 hashcode 才能从 Map/Set 中正确检索其值。但是,如果我使用变异对象作为键而不覆盖哈希码或等于,它的哈希码是否会与它的生命周期一致。我已经尝试用它来检索变异对象的哈希码,并且发现它始终是一致的。

【问题讨论】:

标签: java hashmap hashcode


【解决方案1】:

contract for hashcode 声明:

每当在 Java 应用程序执行期间对同一个对象多次调用时,hashCode 方法必须始终返回相同的整数,前提是没有修改对象上的 equals 比较中使用的信息.

因此,如果您改变对象,则无法保证哈希码不会改变。碰巧一些 JDK 实现可能会使用某种内部地址 but they don't have to,所以你不应该依赖它。

【讨论】:

    【解决方案2】:

    在最新版本的 HotSpot JVM 中,对象的默认哈希码不会随时间改变。实际上,哈希码是从初始分配地址派生出来的,并随着对象被垃圾收集器移动而输入到对象头中(参见JVM Whitepaper),之后不会改变。

    【讨论】:

      【解决方案3】:

      hashcode的默认Java实现是基于指向对象的指针,所以当实例变量改变时它不应该改变。

      编辑

      但是 Martijn 打败了我。

      【讨论】:

        【解决方案4】:

        是的,如果您不覆盖 hashCode 方法,它将保持不变。默认的 hashCode 是对象在内存中的原始位置。此内存位置通过此方法检索:

        System.identityHashCode(Object)

        在 StackOverflow 上查看此线程:

        How does the JVM ensure that System.identityHashCode() will never change?

        【讨论】:

        • 这不是对象在内存中的当前位置——毕竟,随着垃圾收集器的移动,它会随着时间而改变。
        • 老实说,我不确定。我从来没有看过它周围的实现细节:(
        • “默认的 hashCode 是对象在内存中的原始位置。” - 不一定。例如:this previous hotspot implementation 增加了一些随机性。刚刚检查了打开的 JDK 7,它看起来很相似。
        • java 不保证它是恒定的,它取决于 jvm 的实现。
        猜你喜欢
        • 2015-09-18
        • 1970-01-01
        • 1970-01-01
        • 2015-02-10
        • 2011-05-01
        • 2012-03-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多