【发布时间】:2019-04-15 19:55:31
【问题描述】:
Java 的System.identityHashCode()
为给定对象返回与返回相同的哈希码 通过默认方法 hashCode(),无论给定对象的 类覆盖 hashCode()。
该哈希码基于对象标识,因此对于同一个对象,它始终是相同的,无论该对象在对identityHashCode() 的调用之间是否发生了变异。
除此之外,任何两个活对象之间都不会发生哈希冲突(使用一些 Java 运行时):(前者是 Oracle 在下面给出的源代码中的不准确陈述,正如 Jai 的答案显示,正如another bug report 所指出的那样 - 这基本上使我原来的问题无效......)
[...] 垃圾对象很容易回收并且地址空间是 重复使用。冲突是地址空间重用的结果。如果是原 对象保持活动状态(不是 GCed),那么您将不会遇到这个 问题。
.Net中有RuntimeHelpers.GetHashCode(),满足第一个条件,但不满足第二个:
请注意,GetHashCode 总是为相等的对象引用返回相同的哈希码。然而,反之则不然:相等的哈希码并不表示相等的对象引用。特定的哈希码值对于特定的对象引用不是唯一的;不同的对象引用可以生成相同的哈希码。
那么 .Net 中是否有类似 Java 的 identityHashCode() 的东西?
编辑:
有人建议这与Memory address of an object in C# 相同,但它不是,因为内存地址不能在这里(单独)使用,因为内存管理会移动对象,因此地址可能会在对象的生命周期内发生变化.
【问题讨论】:
-
Java 不保证不同的对象会有不同的哈希码。
-
保证与实施细节不同。
-
为什么要删除我添加到您帖子中的
I am trying to build a stable sort algorithm.声明?它确实为您的问题提供了有用的背景。 -
我还怀疑您误解了 Java 是如何做到这一点的。它确实保证了对象的哈希码不会改变(根据stackoverflow.com/questions/3796699/…)。但是如果发生 GC,内存被压缩并且对象被移动到别处,那么没有什么能阻止该类型的新实例占用与“原始”对象相同的内存地址。然后,您将拥有两个具有相同哈希码的对象。因此,您不能声明
In addition to that, there will not be hash collisions between any two living objects。 -
虽然 Java 的
Object#hashCode()和System.identifyHashCode()保证它为特定 instance 返回的值永远不会改变,但它没有提到它将返回一个唯一的值每个对象。事实上,它只返回对象堆中的尾随 32 位内存地址——这意味着0x 0 FFFF FFFF和0x 1 FFFF FFFF都将返回0x FFFF FFFF。您可以修改错误报告的示例,例如创建一个静态列表来存储obj以防止GC,仍然会发生冲突。