[英]If I never ever use HashSet, should I still implement GetHashCode?
我永遠不需要將對象存儲在哈希表中。 原因有兩個:
另一方面,Equals()操作是一種非常常用的功能。
因此我想知道在實現Equals函數(我經常需要)時是否有必要實現GetHashCode(我從不需要)?
我的建議 - 如果你不想使用它,覆蓋它並throw new NotImplementedException();
這樣你就會看到你需要它的地方。
如果您認為實現嚴格的順序謂詞比散列函數更容易實現,我認為您錯了 - 它需要處理大量邊緣情況(空值,類層次結構)。 哈希函數並不那么難 ,真的。
AVL樹比哈希表慢得多。 如果您只處理幾件物品,那么這不會是一個大問題。 Hashtables具有O(1)插入,刪除和搜索,但AVL樹具有O(log(n))操作。
我會繼續並覆蓋GetHashCode
和Equals
有兩個原因。
另外,我不得不質疑BST的選擇。 AVL樹有點不合時宜。 還有其他更現代的BST更容易實現和工作(有時更好)。 如果您確實需要維護排序的數據結構,那么請考慮這些替代方案。
1 XOR策略存在一個微妙的關聯性問題,在某些情況下可能會導致沖突,因為a^b = b^a
。 Effective Java提供了一個解決方案,它實現了類似於邪教的識別,並且實現起來相當簡單。
如果你使用Dictionary
或SortedList
,並重寫Equals
,你需要有一個哈希函數,否則它們會破壞。 Equals
也在BCL中的所有地方使用,如果其他人使用你的對象,他們會期望GetHashCode
表現得合理。
請注意,散列函數不必那么復雜。 基本版本是獲取您用於相等的任何成員變量的哈希值,將每個成員變量與一個單獨的互質數相乘,並將它們一起進行異或。
您不需要實現它。 如果你編寫自己的Equals()方法,我建議使用一些不破壞HashSet的GetHashCode實現。 例如,您可以返回靜態值(通常為42)。 HashSet性能會急劇下降,但至少它仍然可以工作 - 你永遠不會知道將來誰會使用/編輯/維護你的代碼。 (編輯:如果在散列結構中使用這樣的類以便及早發現性能問題,則可能需要記錄警告)
編輯:不要只使用XOR來組合屬性的哈希碼
其他人已經說過,您可以簡單地組合所有屬性的哈希碼。 而不是只使用XOR我會鼓勵倍增結果。 如果兩個值相等(例如0xA ^ 0xA == 0x0
),則XOR可能導致0值。 使用0xA * 0xA
, 0xA * 31 + 0xA
或0xA ^ (0xA * 31)
可以輕松改善這一點。
盡管如此,我的答案的意圖是任何散列函數都優於與equals不一致的函數 - 即使它只返回一個靜態值。 只需選擇用於相等性的任何屬性子集(從none到all)並將結果放在一起。 在選擇哈希碼的屬性時,更喜歡那些組合非常獨特的小子集(例如,名字,姓氏,生日 - 不需要添加整個地址)
提供足夠的哈希函數並不困難。 大多數情況下,所有字段的GetHashCode()
結果的簡單XOR就足夠了。
如果覆蓋equals,則應覆蓋MSDN中的GetHashCode():“建議任何覆蓋Equals的類也覆蓋System.Object.GetHashCode。” http://msdn.microsoft.com/en-us/library/ms173147.aspx
這兩個函數應該匹配,如果兩個對象相等,它們應該具有相同的散列值。 這並不意味着如果兩個對象具有相同的散列,則它們應該相等。 您不需要過於復雜的哈希算法,但它應該嘗試在整數空間中很好地分布。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.