String hashcode 源码分析

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;
}

很简单,就是通过每个字节进行 s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1],那么为什么是31呢?

主要有以下几点:

  1. 31是优质质数,因为31 可以通过移位和减法来代替乘法,例如:31 * i == (i << 5)- i,现在的JVM可以主动完成优化代码。
  2. 31计算出来的hashcode值范围处于一个“适中”的区间,能够很好的降低哈希冲突,进行数据查找时可以提高效率。乘子太小容易导致计算出来的hashcode值区间太小,进行与运算时容易发生hash冲突。而乘子太大可能会导致相乘时造成数据溢出的概率增大,而 int的取值范围 -2^31 -- 2^31-1。 所以31比较合适。
  3. 31是一个奇素数,选择素数(质数)的好处就是如果我用一个数字来乘以这个素数,那么最终出来的结果也只能被素数本身和被乘数(以及被乘数的整除因子)还有1来整除!这样,以31作为乘子参与乘法计算得出的hashcode值,在后面进行取模(实际上是与运算时),得到相同index的概率会降低,即降低了哈希冲突的概率。
  4. 31只占用5bits(11111B),相乘造成数据溢出的概率较小。

这就是String的hashCode 源码实现及其为什么这样实现的原因了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值