javaHashMap

java.util.HashMap类提供了静态的hash方法和indexFor方法:

/**
* Applies a supplemental hash function to a given hashCode, which
* defends against poor quality hash functions. This is critical
* because HashMap uses power-of-two length hash tables, that
* otherwise encounter collisions for hashCodes that do not differ
* in lower bits. Note: Null keys always map to hash 0, thus index 0.
*/
static int hash(int h) {
// This function ensures that hashCodes that differ only by
// constant multiples at each bit position have a bounded
// number of collisions (approximately 8 at default load factor).
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}

/**
* Returns index for hash code h.
*/
static int indexFor(int h, int length) {
return h & (length-1);
}

看hash方法的javadoc可以了解其目的:为了防止低质量的hash方法带来的过多冲突而增加的这个静态的hash方法。核心代码:

h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);

非常的晕,不是吗?还好总有一些牛人走在我们前面进行了分析:

http://nbqwcnm.iteye.com/blog/1126938

(我的理解)简单点说,就是通过上面代码把原本由低质量的hash方法产生的h进行再次hash而得到一个新的整数,这个整数的产生依赖于对原h的每个字节(共8个)按照一定算法进行^处理,从而保证冲突的尽量避免。

每个字节的处理过程如下:

8=8 
7=7^8 
6=6^7^8 
5=5^8^7^6 
4=4^7^6^5^8 
3=3^8^6^5^8^4^7 
2=2^7^5^4^7^3^8^6 
1=1^6^4^3^8^6^2^7^5 
结果中的1、2、3三位出现重复位^运算 
3=3^8^6^5^8^4^7     ->   3^6^5^4^7 
2=2^7^5^4^7^3^8^6   ->   2^5^4^3^8^6 
1=1^6^4^3^8^6^2^7^5 ->   1^4^3^8^2^7^5 

 

再来看看indexFor方法

static int indexFor(int h, int length) {
return h & (length-1);
}

通过hash值h(由HashMap.hash方法确定的)和hash表长度length来确定当前hash值在hash表中的位置。

照理说我们最常见的做法应该是h%length就可以了,而这里为什么要h&(length-1)呢?其实还是从性能的角度考虑的。我们知道如果Hash表长度是2的平方的话h&(length-1)与h%length是等价的,而前者的性能要高很多。

http://nbqwcnm.iteye.com/blog/1126988

 

你可能感兴趣的:(HashMap)