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

标签 java c# .net hash

Java 的 System.identityHashCode()

Returns the same hash code for the given object as would be returned by the default method hashCode(), whether or not the given object's class overrides hashCode().

该散列码基于对象身份,因此无论对象是否在调用 identityHashCode() 期间发生变化,对于同一对象它始终是相同的。

除此之外,任何两个 Activity 对象(与某些 Java 运行时)之间不会发生哈希冲突:(前者是 Oracle 在下面给出的源代码中的不准确声明,因为 Jai 的答案显示,并且 another bug report 也指出 - 这基本上使我原来的问题无效......)

[...] garbage objects are readily reclaimed and the address space is reused. The collisons result from address space reuse. If the original object remains live (not GCed) then you will not encounter this problem.

Source

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

Note that GetHashCode always returns identical hash codes for equal object references. However, the reverse is not true: equal hash codes do not indicate equal object references. A particular hash code value is not unique to a particular object reference; different object references can generate identical hash codes.

那么在.Net中有没有类似Java的identityHashCode()的东西呢?

编辑:

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

最佳答案

当前 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 中,您必须创建自己的某种唯一数字生成器。所以 solution NPras 提供的似乎是为 .NET 做的。

关于java - .Net 相当于 Java 的 System.identityHashCode(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53273279/

相关文章:

java - spring data jpa的奇怪行为

java - ViewModel中的LiveData对象为什么要在声明的时候实例化?

c# - 向客户端发送 ICalendar 事件,同时继续运行您的代码

c# - 使用 NHibernate 为 Sql Server Identity 和 Oracle Sequence 映射实体

java - 获取当前jre的文件路径

c# - 将 WCF 绑定(bind)从 wsHttpBinding 转换为 netTcpBinding

c# - 如何覆盖 ASP.NET MVC 3 默认模型绑定(bind)器以在模型创建期间解决依赖关系(使用 ninject)?

.net - 使用VB.NET查找应用程序路径

c# - 使缓存计算结果线程安全的最高效方法是什么?

java - 使用扫描仪读取输入语句