簡體   English   中英

使用long(int64)作為hashCode並仍將IEqualityComparer用於並發字典

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM