我需要在GetHashCode中为BitArray生成一个快速哈希码。我有一个字典,其中的键是BitArrays,并且所有的BitArrays长度相同。为BitArray生成一个好的哈希码(GetHashCode)
有没有人知道一个快速的方法来从可变数量的位生成一个好的散列,就像在这种情况下一样?
UPDATE:
我原先采取的方法是直接通过反射来访问整数的内部阵列(速度比在这种情况下的封装更重要),然后异或这些值。异或方法似乎运作良好,即我的“等于”在字典搜索时方法不叫过度:
public int GetHashCode(BitArray array)
{
int hash = 0;
foreach (int value in array.GetInternalValues())
{
hash ^= value;
}
return hash;
}
然而,马克拜尔斯建议和StackOverflow上其他地方看到的做法稍好(16570点的Equals我的测试数据用XOR调用vs 16608)。请注意,这种方法修复了前一个错误,即位数组末尾的位可能会影响散列值。如果位阵列的长度缩短,则可能发生这种情况。
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
}
任何改进建议,欢迎!
我已经看到你的方法在其他地方提到过,但我并不真正理解它背后的理论或选择'魔术'素数。这种方法比我原先采用的异或方法稍微有效(对于我的测试数据,异或为16570等于16608)。查看我的编辑了解更多细节。 – bart 2010-06-29 10:21:02