• HashMap初始化数组原理,为什么是2的N次方?


    Jdk1.8初始化hashMap容量的算法

    static final int tableSizeFor(int cap) {
      // 先减1,避免传进来的本来就是2的n次幂,导致算出来多了一次幂,比如传16会得到32,实际上16即可
    int n = cap - 1;
      // 低位全部变1, int4字节*1个字节8位=32位
    n |= n >>> 1;
    n |= n >>> 2;
    n |= n >>> 4;
    n |= n >>> 8;
    n |= n >>> 16;
      //再加1获取2的N次幂作为容量
    return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
    }

    举例,Map map = new hashMap(10)
    10-1=9
    对应二进制    0000 1001

    右移1位     0000 0100
    或运算     0000 1101

    结果右移2位   0000 0011
    或运算 0000 1111

    结果右移4位   0000 0000
    或运算 0000 1111
    ```

    不断右移然后或运算后,最后低位全部变1
    加1后 得到   0001 0000 得到16为最接近10的二的次方数
    hashmap数组容量2的N次幂的好处是:

    查看put方法计算元素数组下标核心代码
    i = (n - 1) & hash

    由于N为2的N次幂,N减1后得到高位为0,低位全为1的二进制
    进行与运算后,不可能得到比N大的数
    举例:

    n= 16,则n-1的二进制为0000 1111
    假设hashcode为**** ****
    与运算后,必定得到 0000 ****,所以不可能大于16,范围为00000000-00001111,即不存在数组越界问题

    这里又会引申出一个问题,这样的话,hashCode的高位的****不是没用了吗,与0000进行与运算后都是0000
    所以在计算hashCode的算法中,会对算出来的hashCode进行右移然后异或运算,使得高位的值保留到低位中去
    举例 hashcode 为1010 0100
    假设右移4位   0000 1010
    异或运算 1010 1110
    这样高位的这两个1就不会完全丢失了
  • 相关阅读:
    Java8新特性
    搜索解决方案 -- ElasticSearch入门
    插入排序
    单点登录系统CAS入门
    快速排序
    选择性排序
    冒泡排序
    springcloud入门
    消息中间件 -- RabbitMQ
    ActiveMQ中消息的重发与持久化保存
  • 原文地址:https://www.cnblogs.com/sulishihupan/p/13372844.html
Copyright © 2020-2023  润新知