Hashcode方法代码解析

几周前学习Java时了解到hashcode方法,它会生成一行唯一的hash值来判定两个目标是否相等,我对这个生成的hash有点疑惑,它是根据什么做的hash呢???难道是根据时间?代码量?内存地址?

这是Java中的String类型hash

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

String类型的hash是使用 String 的 char 数组的数字每次乘以 31 再叠加最后返回,因此,每个不同的字符串,返回的 hashCode 肯定不一样。

我又有疑惑了那么为什么使用 31这个魔数 呢?

在名著 《Effective Java》第 42 页就有对 hashCode 为什么采用 31 做了说明:
之所以使用 31, 是因为他是一个奇素数。如果乘数是偶数,并且乘法溢出的话,信息就会丢失,因为与2相乘等价于移位运算(低位补0)。使用素数的好处并不很明显,但是习惯上使用素数来计算散列结果。 31 有个很好的性能,即用移位和减法来代替乘法,可以得到更好的性能: 31 * i == (i << 5) - i, 现代的 VM 可以自动完成这种优化。这个公式可以很简单的推导出来。
在栈溢出论坛(Stackoverflow)里面有很多小伙伴的讨论,大家可以去看一看。。。
点我 Stackoverflow
好吧,使用 31 最主要的还是为了性能。没有最合适,只有更合适,关于散列计算问题,我在知乎上看到有人做过统计选取,当选取的数大于31时,hash码的分布会非常的分散,很多”数串“没有用到。而选取小于31的数时,hash出来的hash值会存在很高的重复度,而且散列分布很集中。至于31怎么来的,或许是James Gosling老爷子试出来的吧!
如果再往深究,就是数学方面的范畴了。
还有很多人会疑惑就是--------怎么都找不到重复的hashCode的例子。下面来一个

String a=“Aa”;String b=“BB”;

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

posted @ 2019-11-17 14:10  AmosAlbert  阅读(120)  评论(0编辑  收藏  举报