研究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