我们以java 8为例 说明 HashMap的Hash(Key)设计原理:
源码展示:
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
大家都知道上面代码里的key.hashCode()函数调用的是key键值类型自带的哈希函数,返回int型散列值
理论上散列值是一个int型,如果直接拿散列值作为下表访问HashMap数组的话,考虑到2进制32位带符号的int值表示范围从-2147483648到2147483638,前后加起来大概40亿的映射空间,只要哈希函数映射的比较松散,一般应用是很难出现碰撞的。
但是问题是一个40亿长度的数组,内存是放不下的,HashMap扩容之前的数组初始大小为16。所以不能直接使用使用散列值直接作为HashMap数组大小,而是用之前和数组的长度进行“与”运算,得到的值才能用来访问数组下标。源代码如下:
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & h