JDK13-Hashcode源碼分析
要想將一個對象放入集合(比如HashMap)中,你的對象所在的類必須提供hashcode方法,即重寫這個方法,返回一個整數值。
以hashmap中的hashcode爲例:
public final int hashCode() {
return Objects.hashCode(key) ^ Objects.hashCode(value);
}
//每個節點的hashcode是由key的hashcode和value的hashcode進行異或得到的。
//這裏調用了Objects類的hashcode實現方法
Objects類的hashcode方法如下:
public static int hashCode(Object o) {
return o != null ? o.hashCode() : 0;
}//調用了Object的hashcode實現方法
Object的hashcode是一個native(本地)方法
* @see java.lang.System#identityHashCode
@HotSpotIntrinsicCandidate
public native int hashCode();
到這裏我們可以知道,每個類都是Object的子類,在子類裏面各有不同的hashcode的實現方法。
以String類爲例,其hashcode代碼如下:
public int hashCode() {
int h = hash;
if (h == 0 && !hashIsZero) {//根據編碼方式,調用不同類的hashcode方法
h = isLatin1() ? StringLatin1.hashCode(value)
: StringUTF16.hashCode(value);
if (h == 0) {
hashIsZero = true;
} else {
hash = h;
}
}
return h;
}
其中,StringLatin1.hashCode源碼爲
public static int hashCode(byte[] value) {
int h = 0;
for (byte v : value) {
h = 31 * h + (v & 0xff);
}
return h;
}
StringUTF16.hashCode源碼爲
public static int hashCode(byte[] value) {
int h = 0;
int length = value.length >> 1;
for (int i = 0; i < length; i++) {
h = 31 * h + getChar(value, i);
}
return h;
}
至於爲什麼基數是31
1.基數要用質數
質數的特性(只有1和自己是因子)能夠使得它和其他數相乘後得到的結果比其他方式更容易產成唯一性,也就是hash code值的衝突概率最小。
2.選擇31是觀測分佈結果後的一個選擇,不清楚原因,但的確有利。
java八大基本類型沒有hashcode和equals方法,需要轉變爲包裝類才能用hashcode。
//舉例
int num3=10;
System.out.println(Integer.hashCode(num3));
比如Integer包裝類的hashcode就是本身的整數值,這是在Integer類實現的
public static int hashCode(int value) {
return value;
}
基本類型包裝類的hashcode源碼參考以下鏈接
https://blog.csdn.net/realwongp/article/details/88901418