Hashmap源码-hash方法

原文链接:

通俗易懂Hashmap源码解析_java阳开发之路的博客-CSDN博客_hashmap源码

https://www.csdn.net/tags/MtTaEgxsNTYxMDAyLWJsb2cO0O0O.html

·

先看源码:

    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }

 我们点进去这里边的hash()方法:  

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

        原来,这个hash参数也就是hash(key)的意思就是:对key进行一个哈希函数的计算,这个哈希函数就是如果key为null则hash参数为0 ,

        如果key不为null,则计算该key的hashcode值,并将其从高位数据移位到低位、然后进行异或运算。

为什么这里需要将高位数据移位到低位进行异或运算呢?

        这是因为有些数据计算出的哈希值差异主要在高位,而 HashMap 里的哈希寻址是忽略容量以上的高位的,那么这种处理就可以有效避免类似情况下的哈希碰撞

     Hashmap源码-hash方法_第1张图片

参考资料:https://blog.csdn.net/caimengyuan/article/details/61204542

结论:

        1,如果key为null,则将其赋值为整数0;

        2,如果key不为null,

  •         2.1、则先获取该key的hashcode值
  •         2.2、然后(无符号右移)移位得到新值,即,将该hashcode值的16位高位数据,移动到低位,得到一个新值,
  •         2.3、将新值再与刚才的hashcode值去进行异或运算, 
  •         2.4、最终返回异或运算的结果

· 

补充:什么是无符号右移、异或运算?

无符号右移: 右移之后, 无论该数是正数还是负数, 右移之后左边都是补上0。

举例:

异或运算:异或运算的运算法则相当于不带进位的二进制加法:(同为0,异为1

        二进制下用1表示真,0表示假,则异或的运算法则为:0⊕0=0,1⊕0=1,0⊕1=1,1⊕1=0,这些法则与加法是相同的,只是不带进位,

        一句话就是:如果a、b两个值相同,则异或结果为0;如果a、b两个值不相同,则异或结果为1。

·

为什么这里需要将高位数据移位到低位进行异或运算呢?

        这是因为有些数据计算出的哈希值差异主要在高位,而 HashMap 里的哈希寻址是忽略容量以上的高位的,那么这种处理就可以有效避免类似情况下的哈希碰撞

·

观察hashCode()方法:

// 这是计算对象的hsahcode的方法,涉及到内存地址
public native int hashCode();

Hashmap源码-hash方法_第2张图片

        如图所示,可以看出,这个hashCode()方法其实是Object类的一个方法还使用了native关键字修饰。

  这个hashCode()方法使用了native关键字修饰,其实这个native关键字,我们开发的时候是用不到的,这个native关键字是Java调用其他地方(本地函数库接口)的一个关键字,所以这里其实是Java里的Object类会去调用本地函数库中的hashCode()方法,来获取到对象的hashcode值。

·

你可能感兴趣的:(java基础以及JavaWeb,java)