zoukankan      html  css  js  c++  java
  • 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就是重复的。

  • 相关阅读:
    [NOI Online #3 提高组]
    Luogu P3491 [POI2009]SLW-Words
    AtCoder Grand Contest 043
    Luogu P5607 [Ynoi2013]无力回天NOI2017
    AtCoder Grand Contest 041
    Luogu P5070 [Ynoi2015]即便看不到未来
    BZOJ 4367: [IOI2014]holiday假期
    BZOJ 3571: [Hnoi2014]画框
    BZOJ 4456: [Zjoi2016]旅行者
    BZOJ 1111: [POI2007]四进制的天平Wag
  • 原文地址:https://www.cnblogs.com/AmosAlbert/p/12832277.html
Copyright © 2011-2022 走看看