软件构造 关于hashCode的一些问题 Blog-5

软件构造 关于hashCode的一些问题 Blog-5


在课上的时候,我们使用了下面这个例子来说明hashCode如何来重写,但是对于为什么要使用17和31这两个Magic Number,背后的原因还不是很清楚,后来大概探索了一下,现在分享一些结果,主要是来自Effective Java和StackOverflow上的一些观点。
Code-hashCode

为什么要用17

If zero were used as the initial value in step 1, the overall hash value would be unaffected by any such initial fields, which could increase collisions. The value 17 is arbitrary.

上面这句话来自Effective Java中的Item 9,其实我们选择 17 17 的本意其实是它不是 0 0 ,其他的原因没有。所以有不少博主在他们的文章中如果出现需要重写hashCode的时候,并没有一开始使用17,而是用了 1 1 或者其他非零的数。

为什么要用31

The value 31 was chosen because it is an odd prime. If it were even and the multiplication overflowed, information would be lost, as multiplication by 2 is equivalent to shifting. The advantage of using a prime is less clear, but it is traditional. A nice property of 31 is that the multiplication can be replaced by a shift and a subtraction for better performance: 31 * i == (i << 5) - i.

上面这句话同样出自Effecitive Java中的Item 9。也就是我们使用31的原因是它是一个质数,这是最主要的原因,它能够尽量减少在哈希表使用时的冲突,提高查找的实际效率(此处有StackOverflow的网友提到:有人做过实验在超过50000个英文单词上面利用哈希,3133373941产生的冲突都是少于7个的)。另外一个原因,是它更容易计算,对于任何一个数result * 31 = (result << 5) - result,利用移位和加法来实现乘法,速度更快一些。
但是使用31仍然有很多问题
比如很短的字符串就有可能产生冲突,比如“Ca”和“DB”,来自StackOverflow。但是对于其他的一些2的质数次幂,如 2191 2 19 − 1 ,即 524287 524287 ,却不会发生这个问题;
比如现在的计算机已经足够快并且编译器足够好,去优化乘法计算,那么我们也可以去使用37,来自StackOverflow。因为任何一个数result * 37 = (result << 3 + result) << 2 + result

个人看法

我感觉,使用31和17可能有一些技术上面的原因,就像上面所提到的;但是更多的可能是一些traditional的东西在里面,因此我们可以去选择我们认为更好的一些数字,比如谢耳朵最喜欢的73(result * 73 = (result << 3 + result) << 3 + result)等等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值