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