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