美文网首页Java学习笔记程序员
String.hashcode 源码分析

String.hashcode 源码分析

作者: HeartGo | 来源:发表于2017-08-03 17:28 被阅读108次

接触编程这么久了,一直会遇到某些高频词,例如,哈希。hashtable,hashmap,hashset等等等。都有hash一次。那什么是哈希值呢?百度本科解释是,Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。
那是怎么把输入转换成固定长度的散列值呢?我也很好奇。
所以特地找了一下string的hashcode源码。

hashcode()源码

 public int hashCode() {
        int h = hash;
        int len = count;
        if (h == 0 && len > 0) {
            int off = offset;
            char val[] = value;

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

我们通过看源码得知,它里面有个for循环,遍历字符串,每一位的ASCII值都会乘于31的n次幂,这个n的话对于len-index.
例如:我们求abcde的hash code。

        输入abcd
        // 第一步 = (int)'a'  
        // 第二步 = (31 * (int)'a') + (int)'b'  
        // 第三步 = 31 * ((31 * (int)'a') + (int)'b') + (int)'c  
        // 第四步 = 31 * (31 * ((31 * (int)'a') + (int)'b') + (int)'c') + (int)'d'  
        // 第五步 = 31 * (31 * (31 * ((31 * (int)'a') + (int)'b') + (int)'c') + (int)'d') + (int)'e' 
也就abcd的hashcode值为,a*31^4+b*31^3+c*31^2+d*31^1+e*31^0
也就是对每一位的num*31^n,n=len-index进行累加

很多书上都说hashcode值不可逆,通过源码查看,确实不可逆。
为什么是31呢?
看一下解释:
之所以选择值31是因为它是奇数素数。如果它是偶数,并且乘法溢出,则信息将丢失,因为2的乘法相当于移位。使用素数的优点不太清楚,但它是传统的。31的一个很好的特性是,可以用一个移位和一个减法来代替乘法,以获得更好的性能:31×i =(i < 5)- i。现代VMS自动完成这种优化。

相关文章

网友评论

    本文标题:String.hashcode 源码分析

    本文链接:https://www.haomeiwen.com/subject/iquplxtx.html