[英]Generating a good hash code (GetHashCode) for a BitArray
我需要在 GetHashCode 中为 BitArray 生成快速哈希码。 我有一个字典,其中的键是 BitArrays,并且所有 BitArrays 的长度都相同。
有没有人知道一种从可变位数生成良好散列的快速方法,如在这种情况下?
更新:
我最初采用的方法是通过反射直接访问内部整数数组(在这种情况下速度比封装更重要),然后对这些值进行异或。 XOR 方法似乎工作得很好,即在字典中搜索时不会过度调用我的 'Equals' 方法:
public int GetHashCode(BitArray array)
{
int hash = 0;
foreach (int value in array.GetInternalValues())
{
hash ^= value;
}
return hash;
}
然而,Mark Byers 建议并在 StackOverflow 上的其他地方看到的方法稍微好一些(16570 Equals 调用 vs 16608 为我的测试数据的 XOR)。 请注意,此方法修复了前一个方法中的一个错误,即位数组末尾以外的位可能会影响哈希值。 如果位数组的长度减少,则可能会发生这种情况。
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 位,那么考虑旋转你自己的类,这样你就可以访问底层数组而无需复制。
如果位数组是 32 位或更短,那么您只需要将它们转换为 32 位整数(如有必要,用零位填充)。
如果它们可以更长,那么您可以将它们转换为一系列 32 位整数并对它们进行异或,或者更好:使用 Effective Java 中描述的算法。
public int GetHashCode()
{
int hash = 17;
hash = hash * 23 + field1.GetHashCode();
hash = hash * 23 + field2.GetHashCode();
hash = hash * 23 + field3.GetHashCode();
return hash;
}
取自这里。 field1、field2分别对应前32位、后32位等。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.