Boolean.hashCode()
Posted
技术标签:
【中文标题】Boolean.hashCode()【英文标题】: 【发布时间】:2011-04-24 03:52:33 【问题描述】:Boolean 类的hashCode()
方法是这样实现的:
public int hashCode()
return value ? 1231 : 1237;
为什么使用 1231 和 1237?为什么不是别的?
【问题讨论】:
这两个数是足够大的素数。请阅读***上的article on Hash Table 了解更多信息。 【参考方案1】:1231 和 1237 只是两个(足够大)任意素数。任何其他两个大素数都可以。
为什么是素数?
假设我们选择了合数(非素数),比如 1000 和 2000。当将布尔值插入哈希表时,true 和 false 将进入桶 @ 987654324@ resp 2000 % N
(其中N
是桶的数量)。
现在请注意
1000 % 8
与 2000 % 8
相同的存储桶
1000 % 10
与 2000 % 10
相同的存储桶
1000 % 20
与 2000 % 20
相同的存储桶
....
换句话说,它会导致许多冲突。
这是因为 1000 的因式分解 (23, 53) 和 2000 的因式分解 (24, 53) 有很多共同因素。因此选择素数,因为它们不太可能与桶大小有任何共同因素。
为什么大素数。 2 和 3 不行吗? 在计算复合对象的哈希码时,通常会为组件添加哈希码。如果在具有大量桶的哈希集中使用的值太小,则有可能导致对象分布不均匀。
碰撞重要吗?布尔值只是有两个不同的值吗? 地图可以包含布尔值和其他对象。此外,正如 Drunix 所指出的,创建复合对象散列函数的常用方法是重用子组件散列代码实现,在这种情况下,最好返回大素数。
相关问题:
Why use a prime number in hashCode? What is a sensible prime for hashcode calculation? Why does Java's hashCode() in String use 31 as a multiplier?【讨论】:
我想这些已经足够大了。要获得大于 1 的 gcd,您至少需要2*1231 = 2462
存储桶。在这种情况下,碰撞会成为问题吗?
有趣的是,考虑到什么可以放入 int 中,它们并不是真的“相当大”。我想它们足够大,可以很好地与 JDK Hashtable 配合使用,但仍然足够小以最小化计算成本。
是的,我也觉得他们没有那么大。但是你认为更大的素数会带来更高的成本吗?
@Thilo 您需要 1231*1237 = 1,522,747 个桶的倍数才能发生碰撞,这已经足够大了
我想说导致与桶计数的冲突并不是布尔值的真正问题,而是更多关于我们如何获得复合对象的哈希码的常见构造,即通过乘以组件的哈希码有一些常量并将它们相加。【参考方案2】:
除了上面所说的,它还可以是开发者的一个小彩蛋:
真:1231 => 1 + 2 + 3 + 1 = 7
7 - 在欧洲传统中是一个幸运数字;
错误:1237 => 1 + 2 + 3 + 7 = 13
13(又名魔鬼打)- 不吉利的数字。
【讨论】:
以上是关于Boolean.hashCode()的主要内容,如果未能解决你的问题,请参考以下文章