如您所知,在向集合中添加新对时Dictionary,首先计算密钥的哈希值。然后对该 hash 执行按位运算& 0x7FFFFFFF,如集合的源代码中所示。
我有一个问题,如果我对所有内容都理解正确,那么只有在哈希结果为负数的情况下才需要此操作,因为我们int也可以存储负值。而这个操作的结果是另一个数字,它总是正数。
如果是这种情况,那么代替:
int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
int targetBucket = hashCode % buckets.Length;
你可以使用这样的代码:
int hashCode = comparer.GetHashCode(key);
if (hashCode < 0)
{
hashCode = hashCode * -1;
}
int targetBucket = hashCode % buckets.Length;
正确的?
最简洁的答案是不。这有两个原因。首先,您的版本在性能方面要差得多 - 它包含比较和乘法。比较对处理器来说是一个糟糕的操作——它可能会导致很大的性能损失。阅读分支预测。优化器很聪明,它可以修复它,也可能不会。
其次,您的变体有时不起作用。想象一个由 1 和 0 组成的数字。这是可以用这种格式表示的最小数字。如果您对其执行AND操作,它将简单地变成零,这不是负数。但是如果你把它乘以负一......这就是事情变得有趣的地方。
我们看一个字节的例子,比较简单。我们的数字是 10000000b == -128。乘以 -1,我们得到 128。但 128 也是 10000000……它再次变为 -128,因为它不适合一个字节。也就是说,将给定“大小”中可表示的最小整数乘以 -1 就可以得到它自己。这显然不是我们所需要的。