Boolean.hashCode()

131

Boolean类的hashCode()方法的实现如下:

public int hashCode() {
    return value ? 1231 : 1237;
}

为什么要使用1231和1237?为什么不使用其他数字?


1
这两个数字是足够大的质数。请阅读维基百科上关于哈希表的文章获取更多信息。 - Boris Pavlović
2个回答

153

1231和1237只是两个(足够大的)任意质数。其他任意两个大质数也可以。

为什么选择质数?
想象一下,如果我们选择合数(非质数),比如1000和2000。当将布尔值插入哈希表时,truefalse会分别进入桶1000 % N2000 % N(其中N是桶数量)。

现在注意到:

  • 1000 % 82000 % 8进入相同的桶
  • 1000 % 102000 % 10进入相同的桶
  • 1000 % 202000 % 20进入相同的桶
  • ....

换句话说,这会导致许多冲突

这是因为1000(23,53)的因式分解和2000(24,53)的因式分解有很多公共因子。因此选择质数,因为它们不太可能与桶大小有任何公共因子。

为什么选择大的质数?2和3不行吗?
当为复合对象计算哈希码时,常常将组件的哈希码相加。如果在具有大量桶的哈希集中使用过小的值,则有可能导致对象分布不均匀。

冲突是否重要? 布尔值只有两个不同的值?
映射可以包含布尔值和其他对象。另外,正如Drunix所指出的,创建复合对象的哈希函数的常见方法是重用子组件哈希代码实现,在这种情况下,最好返回较大的质数。

相关问题:


2
有趣的是,考虑到 int 可以容纳的内容,它们并不真正地“相当大”。我想它们只是足够大,可以很好地与 JDK Hashtable 协同工作,但仍然足够小,以最小化计算成本。 - Thilo
2
是的,我也注意到它们并不是那么大。但是你认为使用更大的质数会导致更高的成本吗? - aioobe
3
如果要让它们碰撞,那么你需要使用1231*1237=1,522,747倍的桶,这非常大了。 - ratchet freak
2
我认为使用布尔值导致哈希桶冲突并不是真正的问题,更多的是我们如何获取复合对象的哈希码的常见构造方式,即通过将组件的哈希码乘以一些常数并将它们相加。 - Drunix
1
@Chris,犯了个错误。谢谢你指出来。回答已更新。 - aioobe
显示剩余5条评论

5
除了上面提到的内容外,这也可能是开发人员留下的小彩蛋:

true: 1231 => 1 + 2 + 3 + 1 = 7

7 - 在欧洲传统中是幸运数字;

false: 1237 => 1 + 2 + 3 + 7 = 13

13(又称魔鬼十三)- 是个不吉利的数字。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
  • 相关问题