2016-06-13 82 views
0

我發現我工作的兩個數據類型與代碼庫的散列碼的方法,這我不完全理解他們爲什麼選擇:這個GetHashCode方法中的位移值如何改善散列?

public override int GetHashCode() 
{ 
    return x.GetHashCode()^y.GetHashCode() << 2; 
} 

public override int GetHashCode() 
{ 
    return x.GetHashCode()^y.GetHashCode() << 2^z.GetHashCode() >> 2; 
} 

怎樣位移位操作使這些哈希值好點?

+0

你試圖做任何研究主題/谷歌在以下'C#搜索確實有點移位操作使哈希值的任何better'?我會先從那裏開始 – MethodMan

+1

您通常希望將一個或多個(不是全部)值包含在哈希代碼中,以便您可以創建更分散的哈希代碼。例如,在你的第一個例子中,如果你沒有移動其中的一個值,那麼x = 1,y = 2的哈希碼將與x = 2,y = 1相同。但是你需要一個不同的哈希代碼來表示這些實際上是對象的兩個不同的值。 –

回答

2

比方說,您有一個Point數據結構由xy變量表示。如果沒有比特移位的哈希碼的值(1,0)1,以及用於(0,1)哈希碼也將是1。現在做同樣的事情與位轉移,爲(1,0)我們得到的1的哈希碼,但是(0,1)我們現在得到的4

的哈希碼,如果你有相同的輸入,但在什麼位移提供的你想獲得不同的散列碼不同的順序,這樣(1,0)(0,1)不會最終落入相同的散列桶,並降低你的HashSet /字典的性能。

通常你會用一個更大的偏移不僅僅是左移兩次。如果處理Int32.MaxValue附近的散列碼,則位移也會導致數據被截斷。下面是我通常使用

public override int GetHashCode() 
{ 
    unchecked 
    { 
     var hashCode = X; 
     hashCode = (hashCode*397)^Y; 
     hashCode = (hashCode*397)^Z; 
     return hashCode; 
    } 
} 

模式(這是帶有ReSharper的「插入比較法」功能的默認實現。要添加更多的字段,你繼續做hashCode = (hashCode*397)^XXXXXXX

使用*unchecked而不是<<任何大於Int32.MaxValue的值都只是溢出而沒有錯誤。

+0

還值得注意的是,GetHashCode()方法用於''Tuple'(的'實施例如['元組'](https://msdn.microsoft.com/en-us/library/dd268536(V = vs.110 )))是[基於(http://referencesource.microsoft.com/#mscorlib/system/tuple.cs,49b112811bc359fd)'(((H1 << 5)+ H1)^ H2);' –