Hashcode源码分析

研究hashMap的时候,发现了好多坑,现在一一补上吧;

首先是hashcode()方法,这个是Object类里的一个方法,也就是说,任何一个对象都会有hash值,出于好奇,打印了下所有基本类型的hash值:

Byte a = 8;------8
Short b = 8;------8
Integer c = 8;------8
Long d = 8L;------8
Float e = 8.0F;------1090519040
Double f = 8.0D;------1075838976
Character g = '8';------56
Boolean h = true;------1231
String s = "8";------56

可以看到,差别还是很大的

前四个,Byte、Short、Integer、Long的hash值就是本身的value,查看源码可以看到这四个基本类型的hashcode()方法很相似

:强转为int类型,并没有进行特殊处理;Long类型除外,因为value可能超出int取值类型,会有一个处理,将溢出的部分做一个取舍,感兴趣的可以自搜

Byte

public static int hashCode(byte value) {
        return (int)value;
    }

Short

public static int hashCode(short value) {
        return (int)value;
    }

Integer

public static int hashCode(int value) {
        return value;
    }

Long

public static int hashCode(long value) {
        return (int)(value ^ (value >>> 32));
    }

浮点类型的Float

Float实现hashcode()方法时,调用了这个方法:

 public static int floatToIntBits(float value) {
        int result = floatToRawIntBits(value);
        // Check for NaN based on values of bit fields, maximum
        // exponent and nonzero significand.
        if ( ((result & FloatConsts.EXP_BIT_MASK) ==
              FloatConsts.EXP_BIT_MASK) &&
             (result & FloatConsts.SIGNIF_BIT_MASK) != 0)
            result = 0x7fc00000;
        return result;
    }

重点是floatToRawIntBits(value) 方法,惭愧,没看懂,反正大概意思也是转成int;

Double

public static int hashCode(double value) {
        long bits = doubleToLongBits(value);
        return (int)(bits ^ (bits >>> 32));
    }

Double就是Float跟Long的结合吧

布尔类型的hashcode()方法就比较简单了,一共就俩值:true 1231, false 1237

最后讲讲string的hashcode()方法吧 这个用的超级多,但原理也挺简单

先看源码

public int hashCode() {
        int h = hash;//默认为0
        if (h == 0 && value.length > 0) {
            char val[] = value;//将string转成char数组

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

这里详细讲解一下,先分析声明的各个对象的含义

hash 第一次调用hashcode()方法时,会赋值当前String的hash值给hash,第二次及以后调用时就不用再走计算了,这也是为什么要进行一个if判断了

h 最终的hash值 默认为0

value 当前string的char数组

val[i] 当前String的第i个字符对应的int值

重点是for循环里面的逻辑:h = 31 * h + val[i];

不得不说,31这个质数选的很牛逼,贴一个链接,详细解释了原理,我就不赘述了

https://segmentfault.com/a/1190000010799123#item-1

我拿一个字符串做举例吧

String a = "11";

当a第一次调用hashcode()方法时,进入方法里面,hash的值为0

走到if判断时,条件成立,声明val数组,这个val就是{'1','1'},一个char数组

然后往下走到for循环,

当i = 0 时:h = 31 * 0 + val[0]; --------val[0]='1' 因为参与加法运算,char会转成int,而'1'的值为49

计算出结果为h = 49;

当 i = 1时,h = 31 * 49 + val[1];

计算出结果为 h = 1568 ;

所以字段串 "11" 的hashcode值为1568。

好了 hashcode的源码解析就到这了 下一篇开始讲hashmap

 

你可能感兴趣的:(源码,java,字符串,hash)