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