HashMap源码分析(三)hash

这个方法的移位太复杂,有些难看懂,就看看文档上是怎么说的:

 /**

     * 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.

     */

大致意思是这样的:

使用一个hash方法用来改善原先hashCode方法低质量的问题。

这个是很关键的,因为HashMap使用的数组长度是2的次幂,在低位相同的话会产生碰撞。

至于null值,他一直就是放在数组的第一个的

带着这个注释,我们来看看他是怎么通过hash方法来改善HashCode的低质量问题的,怎么降低低位的相同情况,尽量减少碰撞。

1.先来分析一下map中数组的长度length。这个长度是规定要2的次幂的,这就有一个特点,将长度转化成二进制后,不管是多少,总是有一个位上是1,然后其他位上全是0。

这个时候length-1,这个位之后的数字就全是1了。比如过64,二进制是0100 0000,那么他减一就是0011 1111。length先说到这里。

2.再来看下hash方法的实现

static int hash(int h) {       
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }

实在是太复杂了,测试一下把。

public class HashMapSource_hash {
	public static void main(String[] args) {
		transform(64);
		transform(64+32+16);
		transform(1+2+4+8);
	}
	static void transform(int h){
		System.out.println(Integer.toBinaryString(h)+"-->"+Integer.toBinaryString(hash(h)));
	}
	static int hash(int h) {
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }
}

打印结果是这样的:

1000000-->1000100
1110000-->1110111
1111-->1111

这个方法的作用大致就是让低位0多的数在低位也得到几个1,这样有什么好处呢?

结合1来看,length-1的值是全是1的,这样2个进行&运算

如果length比较小,比如说是4,那么length-1的二进制为0000 0011,对于一些hashCode稍微高一点的数,如64.128,他们跟length-1与,得到的都是0,这样就发生了冲撞。这个&的好处就是既保证了速度,又保证了计算后得到的值是在length之内的。

indexFor方法做的就是这个事。

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

—————————————————————————————————————————————————————————————

再来看看jdk1.8的hash方法

static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

这里传递的是一个对象,比之前也简洁了很多

如果是空,返回0,如果不是空,返回hashCode与上hashCode无符号右移16位

hash是int类型的,int类型的最大值的二进制是31个1加上前面一个0,无符号右移16位就是舍弃了它一半的低位,把高位给搬到低位来了

这个方法要做的事就如下图:

《HashMap源码分析(三)hash》

    原文作者:翁英健啊
    原文地址: https://blog.csdn.net/q291611265/article/details/46763053
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞