.Net相当于Java的System.identityHashCode()

问题描述 投票:2回答:2

Java的System.identityHashCode()

返回给定对象的相同哈希码,就像默认方法hashCode()返回的一样,无论给定对象的类是否覆盖hashCode()。

该哈希代码基于对象标识,因此无论对象是否在调用identityHashCode()之间发生变异,它对于同一对象始终是相同的。

除此之外,任何两个活动对象(具有一些Java运行时)之间不会发生哈希冲突: (前者是甲骨文在下面给出的来源中的一个不准确的陈述,正如Jai的答案所示,正如another bug report指出的那样 - 这基本上使我原来的问题无效......)

[...]垃圾对象很容易回收,地址空间可以重复使用。地址空间重用产生了collisons。如果原始对象保持活动状态(不是GCed),那么您将不会遇到此问题。

Source

在.Net中,有RuntimeHelpers.GetHashCode(),它满足第一个条件,但不是第二个条件:

请注意,GetHashCode始终为相等的对象引用返回相同的哈希码。但是,反之则不然:相等的哈希码不表示相等的对象引用。特定的哈希码值对于特定的对象引用不是唯一的;不同的对象引用可以生成相同的哈希码。

那么在.Net中有类似Java的identityHashCode()吗?

编辑:

有人建议这与Memory address of an object in C#不同,因为内存地址不能在这里(单独使用),因为内存管理会移动对象,因此地址可能会在对象的生命周期内发生变化。

java c# .net hash
2个回答
3
投票

目前Java的Object#hashCode()System#identifyHashCode()不能确保返回唯一值。对此已有疑问,this就是一个例子。

您已经提到了一个错误报告,该报告指出发生了冲突,因为对象是垃圾回收的,并且重用了相同的内存地址。但是,修改相同的测试用例将证明不是:

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提供的solution似乎是为.NET做的。


2
投票

我会把你推荐给following answer from Eric Lippert(他是C#语言设计和编译团队的一员),他建议使用ObjectIDGenerator。

要为对象生成唯一ID,您可以使用我们为您方便地提供的恰当名称的ObjectIDGenerator

Looking at the reference source(他们现在开源的好东西),它确实使用RuntimeHelpers.GetHashCode()但也通过分别存储引用来处理潜在的冲突。

请注意他对物体寿命的警告。如果您需要它用于瞬态对象,他建议您重新实现生成器 - 现在您可以更轻松地访问源。

© www.soinside.com 2019 - 2024. All rights reserved.