簡體   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