繁体   English   中英

.Net等效于Java的System.identityHashCode()

[英].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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM