c# - 为 BitArray 生成良好的哈希码 (GetHashCode)

标签 c# .net dictionary gethashcode bitarray

我需要在 GetHashCode 中为 BitArray 生成一个快速哈希码。我有一个字典,其中的键是 BitArray,并且所有 BitArray 的长度都相同。

有谁知道从可变位数生成良好散列的快速方法,就像在这种情况下一样?

更新:

我最初采用的方法是直接通过反射访问内部的整数数组(在这种情况下速度比封装更重要),然后对这些值进行异或。 XOR 方法似乎运行良好,即在字典中搜索时,我的“等于”方法没有被过度调用:

    public int GetHashCode(BitArray array)
    {
        int hash = 0;
        foreach (int value in array.GetInternalValues())
        {
            hash ^= value;
        }
        return hash;
    }

但是,Mark Byers 建议并在 StackOverflow 其他地方看到的方法稍微好一些(16570 Equals calls vs 16608 for XOR for XOR for my test data)。请注意,此方法修复了前一个中的错误,即超出位数组末尾的位可能会影响哈希值。如果位数组的长度减少,就会发生这种情况。

    public int GetHashCode(BitArray array)
    {
        UInt32 hash = 17;
        int bitsRemaining = array.Length;
        foreach (int value in array.GetInternalValues())
        {
            UInt32 cleanValue = (UInt32)value;
            if (bitsRemaining < 32)
            {
                //clear any bits that are beyond the end of the array
                int bitsToWipe = 32 - bitsRemaining;
                cleanValue <<= bitsToWipe;
                cleanValue >>= bitsToWipe;
            }

            hash = hash * 23 + cleanValue;
            bitsRemaining -= 32;
        }
        return (int)hash;
    }

GetInternalValues 扩展方法是这样实现的:

public static class BitArrayExtensions
{
    static FieldInfo _internalArrayGetter = GetInternalArrayGetter();

    static FieldInfo GetInternalArrayGetter()
    {
        return typeof(BitArray).GetField("m_array", BindingFlags.NonPublic | BindingFlags.Instance);
    }

    static int[] GetInternalArray(BitArray array)
    {
        return (int[])_internalArrayGetter.GetValue(array);
    }

    public static IEnumerable<int> GetInternalValues(this BitArray array)
    {
        return GetInternalArray(array);
    }

... more extension methods
}

欢迎提出任何改进建议!

最佳答案

在字典中充当键是一个糟糕的类。实现 GetHashCode() 的唯一合理方法是使用其 CopyTo() 方法将位复制到 byte[]。这不是很好,它会产生大量垃圾。

乞求、偷窃或借用 BitVector32 代替。它有一个很好的 GetHashCode() 实现。如果你有超过 32 位,那么考虑旋转你自己的类,这样你就可以到达底层数组而无需复制。

关于c# - 为 BitArray 生成良好的哈希码 (GetHashCode),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3125676/

相关文章:

c# - EF Core LINQ 从包含的实体中排除列

c# - TryGetValue 线程本身是否安全

c# - 将托管 dll 注入(inject) native 进程

c# - 如何从列表框 C# 中删除选定的项目

c# - 寻找有关在本地磁盘上存储数据的想法

c# - 有没有一种简单的方法可以通过名称(来自文本文件)来处理应用程序的变量?

.net - Windows Phone 7 有温度传感器吗?

arrays - 无法使用 '[AnyHashable : Any]' 类型的索引为 'Any?' 类型的值添加下标

python - 将字典中的多个值(每个键)映射并附加到数据帧的不同列

c# - 自定义角色存储 asp.net