[英]Efficiency of using IEqualityComparer in Dictionary vs HashCode and Equals()
[英]using long (int64) as a hashCode and still use IEqualityComparer for concurrent Dictionary
我在並發字典中使用自制的IEqualityComparer和GetHashCode遇到問題。
當我像這樣實現它時,下面的類(用兩個屬性簡化)可以完美工作:
ConcurrentDictionary<TwoUintsKeyInfo,Int64> hashCodePlusIandJDict = new ConcurrentDictionary<TwoUintsKeyInfo, Int64>();
。
public class TwoUintsKeyInfo
{
public uint IdOne { get; set; }
public uint IdTwo { get; set; }
#region Implemetation of the IEqualityComparer
public class EqualityComparerTwoUintsKeyInfo : IEqualityComparer<TwoUintsKeyInfo>
{
System.Reflection.PropertyInfo[] properties;
bool propertyArraySet=false;
public int GetHashCode(TwoUintsKeyInfo obj)
{
unchecked
{
if(!propertyArraySet)
{
properties = obj.GetType().GetProperties().OrderBy(x => x.Name).ToArray();
propertyArraySet = true;
}
decimal hash = 17;
int counter=0;
foreach(System.Reflection.PropertyInfo p in properties)
{
counter++;
var value = p.GetValue(obj);
decimal unique = (decimal)Math.Pow(Math.E, counter);
hash = hash + (value == null ? unique : value.GetHashCode() * unique);
}
return 2147483647M * .001M > hash ? (int)(hash * 1000) : (int)hash;
}
}
public bool Equals(TwoUintsKeyInfo x, TwoUintsKeyInfo y)
{
return GetHashCode(x) == GetHashCode(y);
}
}
#endregion Implemetation of the IEqualityComparer
}
現在,我制作了幾乎相同的類,但是與常規的IEqualityComparer接口不同,我做了一些更改,因此可以生成long / int64 hascodes(因為當該類擁有越來越多的屬性時,我們遇到了多個具有相同哈希碼的值)
所以我想減少獲取相同hascode的更改。 因此,我想使用更大的數字,並且如果可能的話,可以使用10000的倍數來獲得一些小數。
因此,我創建了以下接口:
public interface IEqualityComparerInt64<in T>
{
bool Equals(T x, T y);
Int64 GetHashCode(T obj);
}
並更改了屬性類,如下所示:
public class TwoUintsKeyInfoInt64
{
public uint IdOne { get; set; }
public uint IdTwo { get; set; }
#region Implemetation of the IEqualityComparer
public class EqualityComparerTwoUintsKeyInfoInt64 : IEqualityComparerInt64<TwoUintsKeyInfoInt64>
{
System.Reflection.PropertyInfo[] properties;
bool propertyArraySet=false;
decimal _upperThreshold,_lowerThreshold;
public EqualityComparerTwoUintsKeyInfoInt64()
{
_upperThreshold = long.MaxValue * .0001M;
_lowerThreshold = -long.MaxValue * .0001M;
}
public long GetHashCode(TwoUintsKeyInfoInt64 obj)
{
unchecked
{
if(!propertyArraySet)
{
properties = obj.GetType().GetProperties().OrderBy(x => x.Name).ToArray();
propertyArraySet = true;
}
decimal hash = 17;
int counter=0;
foreach(System.Reflection.PropertyInfo p in properties)
{
counter++;
var value = p.GetValue(obj);
decimal unique = (decimal)Math.Pow(Math.E, counter);
hash = hash + (value == null ? unique : value.GetHashCode() * unique);
}
return _upperThreshold > hash && _lowerThreshold < hash ? (long)(hash * 10000) : (long)hash;
}
}
public bool Equals(TwoUintsKeyInfoInt64 x, TwoUintsKeyInfoInt64 y)
{
return GetHashCode(x) == GetHashCode(y);
}
}
#endregion Implemetation of the IEqualityComparer
}
GetHashCode工作正常。 到目前為止沒有問題。
但是...當我嘗試像這樣向並發字典添加IEqualityComparer時:
ConcurrentDictionary<TwoUintsKeyInfoInt64,Int64> hashCodePlusIandJDict = new ConcurrentDictionary<TwoUintsKeyInfoInt64, Int64>(new TwoUintsKeyInfoInt64.EqualityComparerOneUintAndTwoStringKeyInfo());
我收到此錯誤:
錯誤3參數1:不能從'HasCodeTestForUniqueResult.TwoUintsKeyInfoInt64.EqualityComparerOneUintAndTwoStringKeyInfo'轉換為'System.Collections.Generic.IEqualityComparer'D:\\ Users \\ mldz \\ Documents \\ visual studio 2012 \\ HashCodeTestTestUniqueResult \\ HashCodeTestForUniqueResult \\ Form1。
我知道默認System.Collections.Generic.IEqualityComparer的int類型與我自己的GetHashCode生成器的long / int64結果之間存在沖突。 但是,有什么辦法可以解決這個問題,並能夠使用較長的HashCodes?
親切的問候,
Matthijs
PS上面的代碼只是為了測試它並復制問題。
根據這個 ,你不能使用長哈希碼,所以問題的答案是否定的。
但是您可以擁有唯一的組合,而不是唯一的值; 解決方案是實現分區系統,這意味着擁有字典的字典,例如:
public class MyClass
{
Dictionary<uint, Dictionary<uint, Int64>> PartDict;
Int64 ReadValue(uint id1, uint id2)
{
return (PartDict[id1])[id2];
}
void AddValue(uint id1, uint id2, Int64 value)
{
Dictionary<uint, Int64> container;
if (!PartDict.TryGetValue(id1, out container))
{
container = new Dictionary<uint, Int64>();
PartDict.Add(id1, container);
}
container.Add(id2, value);
}
}
這樣,您將擁有一個哈希碼列表,每個哈希碼將再次具有一個哈希碼列表,該組合是唯一的。 但是,任何讀取和寫入操作都將分兩個步驟進行(考慮到您是否需要唯一的哈希值來提高性能)。
希望能幫助到你。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.