hashcode代码的解析以及为啥要取31作为系数

在hashcode中,总而言之就是要产生尽可能不重复的hashCode值

下图的 value.length 为你传入的String字符串的长度,同理可推(传入的是 String a = "abcde" ),长度就为5

  val[i]其实就是传入字符串的ascii值,如果传入的位abcde,则val[1]=97,val[2]=98;

    public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

这个算法写的很巧妙,假设传入的是abcde,则运行结果其实如下:

a*31^4+b*31^3+c*31^2+d*31^1+e*31^0。也就是一个31进制的数转换成了一个10进制的数。

关于这个系数31,这个网上讲的很多,下面是官方的说法,从一本书上摘抄过来的:(其实使用31是有一定争议的)

之所以使用 31, 是因为他是一个奇素数。如果乘数是偶数,并且乘法溢出的话,信息就会丢失,

(小编注:这句话其实是不成立的,关于这个问题我问过一些博士的大佬,

                  给出的答案是其实无论选什么数最终都会有乘法溢出)

因为与2相乘等价于移位运算(低位补0)。使用素数的好处并不很明显,但是习惯上使用素数来计算散列结果。 31 有个很好的性能,即用移位和减法来代替乘法,可以得到更好的性能: 31 * i == (i << 5) - i, 现代的 VM 可以自动完成这种优化。这个公式可以很简单的推导出来。

下面这篇文章介绍了两个结论:
1.基数要用质数
质数的特性(只有1和自己是因子)能够使得它和其他数相乘后得到的结果比其他方式更容易产成唯一性,也就是hash code值的冲突概率最小。
2.选择31是观测分布结果后的一个选择,不清楚原因,但的确有利。

http://computinglife.wordpress.com/2008/11/20/why-do-hash-functions-use-prime-numbers/

如果面试问起 选择31的原因,那么你就说上面两个结论,如果再往深究,就是数学方面的范畴了

还有很多人会疑惑就是--------怎么都找不到重复的hashCode的例子。下面来一个

String a="Aa";String b="BB";

int c=a.hashCode();   2122  int d=b.hashCode();2112  所得hashCode就是重复的了

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值