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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章