3 回答

TA貢獻1777條經驗 獲得超3個贊
我個人會避免XOR-這意味著任何兩個相等的值都將導致0-因此hash(1,1)== hash(2,2)== hash(3,3)等。另外hash(5,0) == hash(0,5)等可能偶爾出現。我已經刻意用它集合散列-如果你想哈希項目的順序,你不關心的排序,這是不錯的。
我通常使用:
unchecked
{
int hash = 17;
hash = hash * 31 + firstField.GetHashCode();
hash = hash * 31 + secondField.GetHashCode();
return hash;
}
這就是Josh Bloch在Effective Java中建議的形式。上次回答類似的問題時,我設法找到了一篇文章進行了詳細討論-IIRC,沒有人真正知道它為什么運作良好,但確實如此。它也很容易記住,易于實現,并且易于擴展到任意多個字段。

TA貢獻1808條經驗 獲得超4個贊
盡管在Jon Skeet的答案中概述的模板通常可以很好地作為哈希函數系列使用,但是常量的選擇很重要,答案中指出的種子17和因數31對于普通用例來說根本無法正常工作。在大多數使用情況下,散列的值比都更接近于零int.MaxValue,并且共同進行散列的項目數不超過幾十個。
對于散列一個整數的元組{x, y},其中-1000 <= x <= 1000和-1000 <= y <= 1000,它有將近98.5%的深不可測的碰撞率。例如{1, 0} -> {0, 31},{1, 1} -> {0, 32}等等。如果我們擴大覆蓋范圍還包括n元組在那里3 <= n <= 25,但它確實不太可怕的約38%的碰撞率。但是我們可以做得更好。
public static int CustomHash(int seed, int factor, params int[] vals)
{
int hash = seed;
foreach (int i in vals)
{
hash = (hash * factor) + i;
}
return hash;
}
我寫了一個蒙特卡洛采樣搜索循環,用隨機種子的各個隨機n元組的各種種子和因子值測試了上述方法i。允許的范圍為2 <= n <= 25(其中n為隨機范圍,但偏向范圍的下限)和-1000 <= i <= 1000。每個種子和因子對至少進行了1200萬次唯一的碰撞測試。
運行大約7小時后,最好對發現(其中種子和因子均被限制為4位數字或更少)為:seed = 1009,factor = 9176,用0.1131%的碰撞率。在5位和6位數字區域,甚至存在更好的選擇。但是為了簡潔起見,我選擇了性能最高的4位數字,并且在所有常見int和char哈希情況下,它的表現都很好。對于更大的整數,它似乎也可以正常工作。
值得注意的是,“成為主要人物”似乎并不能作為取得種子和/或因素良好表現的一般先決條件,盡管它可能會有所幫助。1009上面提到的實際上是素數,但9176不是。我明確測試了這種變化,在factor附近9176(離開seed = 1009)更改為各種素數,它們的表現都比上述解決方案差。
最后,我還對比了通用的ReSharper推薦功能系列hash = (hash * factor) ^ i;和CustomHash()上面提到的原始功能嚴重勝過它。對于常見的用例假設,ReSharper XOR樣式的沖突率似乎在20%至30%的范圍內,我認為不應使用。

TA貢獻1835條經驗 獲得超7個贊
如果使用的是.NET Core 2.1或更高版本,請考慮使用System.HashCode結構來幫助生成復合哈希碼。它具有兩種操作模式:添加和合并。
使用的示例Combine,通常更簡單,最多可處理八個項目:
public override int GetHashCode()
{
return HashCode.Combine(object1, object2);
}
使用示例Add:
public override int GetHashCode()
{
var hash = new HashCode();
hash.Add(this.object1);
hash.Add(this.object2);
return hash.ToHashCode();
}
優點:
從.NET Core 2.1 / .NET Standard 2.1開始的.NET本身的一部分(盡管請參閱下面的con)
根據作者和審閱者在合并到corefx存儲庫中之前所做的工作,看起來具有良好的性能和混合特性。
自動處理空值
需要IEqualityComparer實例的重載
缺點:
在.NET Framework上不可用。HashCode是.NET Standard 2.1的一部分,但截至2019年9月,.NET團隊尚無計劃在.NET Framework上支持.NET Standard,因為.NET Core / .NET 5是.NET的未來。
通用,因此將無法處理超特定情況以及手工編寫的代碼
添加回答
舉報