[英].Net equivalent of Java's System.identityHashCode()
Java的System.identityHashCode()
无论给定对象的类是否覆盖hashCode(),都为给定对象返回与默认方法hashCode()返回的哈希码相同的哈希码。
该哈希码是基于对象标识的,因此对于同一对象它始终是相同的,无论对象在对identityHashCode()
调用之间是否发生了突变。
除此之外,任何两个活动对象(带有某些Java运行时)之间都不会发生哈希冲突:(
前者是Oracle在下面给出的源代码中的不准确陈述,正如Jai的回答所示, 另一错误报告指出以及-这基本上使我原来的问题无效...)
垃圾对象很容易被回收,地址空间被重用。 Collisons是地址空间重用的结果。 如果原始对象保持活动状态(未GCed),则不会遇到此问题。
在.Net中,有RuntimeHelpers.GetHashCode()
,它满足第一个条件,但不满足第二个条件:
请注意,GetHashCode始终为相同的对象引用返回相同的哈希码。 但是,事实并非如此:相等的哈希码并不表示相等的对象引用。 特定的哈希码值对于特定的对象引用不是唯一的。 不同的对象引用可以生成相同的哈希码。
那么,.Net中是否有类似Java的identityHashCode()
东西?
编辑:
建议这与C#中对象的内存地址相同,但与C#中的对象的内存地址不同 ,这是因为内存管理会移动对象,因此此处(仅)不能使用内存地址(因此)。宾语。
当前,Java的Object#hashCode()
和System#identifyHashCode()
不能确保返回唯一值。 对此已经存在疑问, 这是一个示例。
您提到了一个错误报告,该报告指出发生冲突是因为对象被垃圾回收,并且相同的内存地址被重用。 但是,修改相同的测试用例将证明相反:
List<Object> allObjs = new ArrayList<>(); // Used to prevent GC
Set<Integer> hashes = new HashSet<Integer>(1024);
int colls = 0;
for (int n = 0; n < 100000; n++)
{
Integer obj = new Integer(88);
allObjs.add(obj); // keep a strong reference to prevent GC
int ihash = System.identityHashCode(obj);
Integer iho = Integer.valueOf(ihash);
if (hashes.contains(iho))
{
System.err.println("System.identityHashCode() collision!");
colls++;
}
else
{
hashes.add(iho);
}
}
System.out.println("created 100000 different objects - "
+ colls
+ " times with the same value for System.identityHashCode()");
System.out.println("Size of all objects is " + allObjs.size());
System.out.println("Size of hashset of hash values is " + hashes.size());
结果:
System.identityHashCode() collision!
System.identityHashCode() collision!
System.identityHashCode() collision!
created 100000 different objects - 3 times with the same value for System.identityHashCode()
Size of all objects is 100000
Size of hashset of hash values is 99997
在链接的SO问题中,还提到了在JRE的某些实现中,冲突率大大降低了 。 但是,似乎没有实现能够防止所有冲突。 因此,即使在Java中,也无法确保哈希码的唯一性。
因此,不要简单地相信一个来源。 评论它的人也只是Oracle团队的成员,而他或她很可能不是设计它的人。
在C#和Java中,您都必须创建自己的某种独特的数字生成器。 因此,NPras提供的解决方案似乎适用于.NET。
我想请您参考Eric Lippert (他是C#语言设计和编译器团队的成员)的以下回答 ,他在其中建议使用ObjectIDGenerator。
要为对象生成唯一的ID,您可以使用我们方便地为您提供的适当命名的
ObjectIDGenerator
查看参考源 (好消息是他们现在开放了框架的源代码),它确实使用RuntimeHelpers.GetHashCode()
但也通过单独存储参考来处理潜在的冲突。
请注意他关于对象寿命的警告。 如果您需要临时对象,他建议您重新实现生成器-现在可以更轻松地访问源。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.