目录
三、HashMap 在计算bucket位置时,为什么使用 & 与运算代替模运算?
hashcode事一个int类型的数字,从Object的hashCode()方法的注释中可以看出hashcode主要是用于hashMap等类用于寻址的一个参数
一、hashCode算法实现
1、对象默认的hashCode()方法:对象如果没有重写hashCode()方法,那么就是继承Object的hashCode()方法,这是一个本地(native)方法,返回实例对象的内存地址(注释中有说明)
//return distinct integers for distinct objects. (This is typically implemented by
//converting the internal address of the object into an integer
public native int hashCode();
2、String类的hashCode()方法:String在内存中是以char数组的形式存储的,hashCode()方法是对每个char字符运算得到
//private final char value[];
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
至于为什么使用31,在《Effective Java》中给出了解释:
因为31是一个奇素数。如果乘数是偶数,并且乘法溢出的话,信息就会丢失,因为与2相乘等价于移位运算(低位补0)。使用素数的好处并不很明显,但是习惯上使用素数来计算散列结果。 31 有个很好的性能,即用移位和减法来代替乘法,可以得到更好的性能: 31 * i == (i << 5) - i, 现代的 VM 可以自动完成这种优化。
3、HashMap的hashCode()方法:hashMap的hashCode是对map中所有Entry的hashCode累加的结果
//(AbstractMap类中)
public int hashCode() {
int h = 0;
Iterator<Entry<K,V>> i = entrySet().iterator();
while (i.hasNext())
h += i.next().hashCode();
return h;
}
而Entry的hashCode计算如下:
//Entry的hashCode(HashMap类中)
public final int hashCode() {
return Objects.hashCode(key) ^ Objects.hashCode(value);
}
//Objects类的hashCode
public static in