使用long (int64)作为hashCode,并且仍然使用IEqualityComparer作为并发字典

本文关键字:IEqualityComparer 字典 并发 int64 long 作为 hashCode 使用 | 更新日期: 2023-09-27 17:50:03

我在并发字典中使用自制的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接口,我做了一点改变,所以我可以生成长/int64 hascodes(因为当类持有越来越多的属性时,我们遇到了具有相同hashcode的多个值)

所以我想减少得到相同的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工作正常。到目前为止没有问题。

但是…当我尝试像这样向concurrentdictionary添加一个IEqualityComparer时:

    ConcurrentDictionary<TwoUintsKeyInfoInt64,Int64> hashCodePlusIandJDict = new ConcurrentDictionary<TwoUintsKeyInfoInt64, Int64>(new TwoUintsKeyInfoInt64.EqualityComparerOneUintAndTwoStringKeyInfo());

我得到这个错误:

错误3参数1:不能从"HasCodeTestForUniqueResult.TwoUintsKeyInfoInt64.EqualityComparerOneUintAndTwoStringKeyInfo"来"System.Collections.Generic。IEqualityComparer ' D: ' ' mldz ' '视觉资料工作室2012'HashCodeTestForUniqueResult'HashCodeTestForUniqueResult'Form1.cs 109 140 HashCodeTestForUniqueResult

我知道默认System.Collections.Generic.IEqualityComparer的int类型和我自己的GetHashCode生成器的long/int64结果之间存在冲突。但有没有办法解决这个问题,并能够使用长HashCodes?

亲切的问候,

Matthijs

注:上面的代码只是为了测试它并复制问题。

使用long (int64)作为hashCode,并且仍然使用IEqualityComparer作为并发字典

根据这一点,你不能使用长哈希码,所以这个问题的答案是否定的。

但是你可以有唯一的组合而不是唯一的值;解决方案是实现一个分区系统,这意味着有一个字典的字典,如:

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);
    }
}

这样你将有一个哈希码列表,每个哈希码将再次有一个哈希码列表,组合是唯一的。任何读取和写入都将在两个步骤中完成(如果您想要唯一的哈希以提高性能,请考虑)。

希望能有所帮助。

相关文章:
  • 没有找到相关文章