• 【Java面试小短文】HashMap中的hash方法为什么要右移16位并异或?


    欢迎关注Java面试系列,不定期更新面试小短文。欢迎一键三连!

    HashMap中的hash方法为什么要右移16位并异或?

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

      原因是为了让hash值的散列度更高,尽可能的去减少hash表的hash冲突,从而去提升数据的查找性能。

        public V put(K key, V value) {
            return putVal(hash(key), key, value, false, true);
        }
    
        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 ((p = tab[i = (n - 1) & hash]) == null)
                tab[i] = newNode(hash, key, value, null);
            // .......源码自行查看,只展示关键部分
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

      在HashMapput方法里面,是通过keyhash值与数组的长度取模计算得到的一个数组位置。而在绝大部分情况下,n的值一般是小于2^16(就是65536),这就意味着 i 的值始终是使用hash值的低16位与(n - 1)进行取模计算,这是由 & 运算符的特点决定的,这样就会造成key的散列度不是很高,导致大量的key集中存储在一个固定的几个数组位置上,很显然这会影响到数据的查找性能。因此为了提升keyhash值的一个散列度,在hash方法里面做了一个位移运算。

      所以在hash方法里面,首先使用keyhashCode无符号右移16位,意味着把hashCode的高位移动到了低位,然后再用hashCode与右移之后的值进行异或运算。就相当于把高位和低位的特征进行了组合,这样通过高位和低位组合后的hashCode通过 & 运算符进行运算后,它得到的一个数组的位置的散列度一定会更高,通过这种方式,可以去降低hash冲突的概率。

    上面说是通过keyhash值与数组的长度取模计算得到的一个数组位置。取模计算?哪里取模了?(n - 1) & hash是取模吗?
    真的是取模,只要n是2的指数幂,就可以将取模运算改成位运算
    比如:13 % 4 = 1 —> 13 & (4 - 1) = 1
     00001101 (13)
    & 00000011  (4 - 1)
    = 00000001  (1)
    比如 14 % 8 = 6 —> 14 & (8 - 1) = 6
     00001110 (14)
    & 00000111  (8 - 1)
    = 00000110  (6)


    你学到了吗


    欢迎一键三连~

    有问题请留言,大家一起探讨学习

    ----------------------Talk is cheap, show me the code-----------------------
  • 相关阅读:
    快速排序-排序-数据结构和算法
    Android自定义控件(五) 自定义View实现Android Loading效果
    Servlet运行原理_API详解_请求响应构造进阶之路(Servlet_2)
    不可不知 | 一份来自官方的量化参赛指南
    基于java(springboot)零食商店管理系统源码(java毕业设计)
    纳什均衡求解器
    10.17数电第二次实验
    Uncaught TypeError: Cannot use ‘in‘ operator to search for ‘path‘ in undefined
    【python学习第9节笔记,面向对象(继承,封装,多态),zip函数,with语句】
    两台linux 之间传输文件 (详细+bash脚本)
  • 原文地址:https://blog.csdn.net/qq_34115899/article/details/126367040