[英]How well does .NET dictionary resolve collisions?
我有一個需要鍵入表的自定義對象的問題。 我需要生成一個唯一的數字鍵。 我有碰撞問題,我想知道我是否可以利用字典來幫助我。 假設我有一個這樣的對象:
class Thingy
{
public string Foo;
public string Bar;
public string Others;
}
等等有更多領域。 讓我們說Foo和Bar是我的關鍵字段 - 如果它們在兩個Thingys之間相等,那么這兩個對象應該被認為是相等的(一個可能代表對另一個的更新,其他字段正在更新。)所以我有這些:
public override bool Equals(object obj)
{
Thingy thing = (Thingy)obj; // yes I do type check first
return (this.Foo == thing.Foo && this.Bar == thing.Bar);
}
public override int GetHashCode()
{
return (this.Foo + this.Bar).GetHashCode(); // using default string impl
}
所以這在很大程度上是有效的,但是在極少數情況下,兩個實際上不同的Thing具有相同的哈希碼。
我的問題是:我可以使用字典<Thingy, int
>放入我的Thingys,並使用字典中的順序值作為我的實際鍵嗎? 我想知道,當檢測到罕見的哈希代碼沖突時,字典是否會調用我的Equals方法,確定對象實際上是不同的,並以不同方式存儲它們。 我在查找時進行成像,它會看到該哈希的桶並搜索正確的Thingy,再次使用Equals進行比較。
這是字典的情況,還是僅解決哈希碼不同的沖突,但(哈希值大小)是否相同? 如果這不起作用,可能會怎樣?
散列沖突只影響性能,而不影響完整性。
一個簡單的測試是將GetHashCode()改為簡單地返回1;。 你會注意到字典仍然表現得很好,但是對於任何合理的數據集,它都會表現得非常糟糕。
散列沖突主要影響性能 - 而不是正確性。 只要Equals()
行為正確。
Dictionary
使用哈希碼作為將項目組織成單獨的“桶”的方式。 如果太多項共享相同的哈希代碼,則可能會遇到性能問題。 但是,只要Equals()
可以正確區分實例,就應該得到正確的結果。
哈希碼可能導致問題的地方是可變對象 。 如果您的Thingy
類允許Foo
或Bar
更改字典中的項目,則您可能無法在后續訪問嘗試中找到它。 這是因為現在生成的哈希碼與用於在字典中存儲值的哈希碼不同。
GetHashCode設計用於哈希表,其中沖突需要最小化但不能消除。 如果你需要生成一個真正唯一的密鑰,GetHashCode是一個合理的起點(並不像guid那么長),但你需要將密鑰存儲為對象的一部分並單獨維護一個使用過的密鑰列表。
雖然您可能能夠從Dictionary的內部檢索看起來可用的東西,但它可能無法可靠地工作 - 例如,如果添加的項目多於最初分配用於處理的字典,則基礎數據結構將重建並且單個項目最終可能會出現在字典中完全不同的部分。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.