hashCode方法里为什么要用31这个数字作为生成hashCode值的常数

本文详细分析了Java中String类的hashCode()方法的实现原理,解释了为何选择31作为乘数的原因。一方面,使用31可以降低哈希冲突的概率;另一方面,31在JVM中可以通过位运算进行优化,提高计算效率。哈希值在对象比较、字符串等值判断中起到关键作用,但为了避免冲突,还需通过equals方法进行确认。
摘要由CSDN通过智能技术生成
    /**
     * Returns a hash code for this string. The hash code for a
     * {@code String} object is computed as
     * <blockquote><pre>
     * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
     * </pre></blockquote>
     * using {@code int} arithmetic, where {@code s[i]} is the
     * <i>i</i>th character of the string, {@code n} is the length of
     * the string, and {@code ^} indicates exponentiation.
     * (The hash value of the empty string is zero.)
     *
     * @return  a hash code value for this object.
     */
    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;
    }

上述为Java中String类的hashCode源码,可以看到其中使用了31作为计算hash值的一个固定常量,那么为什么要用31作为常数,而不是其他的值呢?

原因一:发生哈希冲突的可能性更低

31在质子数中“不大不小”,如果使用一个较小的质数如2,那么算出来的哈希值会在一个很小的范围,就会很容易造成哈希值的冲突。而如果选择100以上的质数,算出来的哈希值会超过int的范围(-2147483648 ~ 2147483647),所以这两种都不合适。根据测试,对超过50000个英文单词使用常数 31,33,37,39,41 作为乘子进行哈希值运算,每个常数算出来的哈希值冲突都小于7个,那么这几个数就被作为生成哈希值的备用乘数了,那么这么多个该用那个更好呢?还有第2个原因

 

原因二:31可以被JVM优化

JVM里最有效的计算方式就是进行位运算了:

* 左移 << : 左边的最高位丢弃,右边补全0(把 << 左边的数据*2的移动次幂)。
* 右移 >> : 把>>左边的数据/2的移动次幂。
* 无符号右移 >>> : 无论最高位是0还是1,左边补齐0。   

       所以 : 31 * i = (i << 5) - i(左边  31*2=62,右边   2*2^5-2=62) - 两边相等,JVM就可以高效的进行计算啦。。。

 

哈希值通常用于比较对象/字符串/值等是否相等,如果2个字符串的哈希值不相等,那么这两个字符串肯定不相等(原始输入相等的话,算出来的哈希值肯定一样的)。但是,要证明两个字符串相等,除了哈希值要一样,还需要用equals方法判断(会出现哈希值冲突的情况)。

 

参考链接https://www.cnblogs.com/0813lichenyu/p/8367103.html

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值