zoukankan      html  css  js  c++  java
  • 记jdk1.8中hashmap的tableSizeFor方法

    static final int tableSizeFor(int cap) {
            int n = cap - 1;
            n |= n >>> 1;
            n |= n >>> 2;
            n |= n >>> 4;
            n |= n >>> 8;
            n |= n >>> 16;
            return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
    }
    

     下面是官方注释:

    Returns a power of two size for the given target capacity.   百度翻译:(返回给定目标容量的二次幂。)

    也就是获取比传入参数大的最小的2的N次幂。
    比如:传入8,就返回8,传入9,就返回16.
    为什么要用这个方法呢?
    MAXIMUM_CAPACITY常量上有这么一句注释:MUST be a power of two <= 1<<30
    就是容量必须是2 的n次冥。而且最大容量是2的30次方。
    这几涉及到hashmap的Node<K,V>[]角标的问题了,我们都知道hashmap首先是存到一个数组中的,也就是Node<K,V>[]中,如果想要传入的key均匀的分布到这个数组中,
    就需要hashmap的容量是2的N次冥了。
    具体的可以看看https://blog.csdn.net/a_long_/article/details/51594159这篇文章。


    下面我们来说说这个方法为什么可以获取到2的N次冥把。

    首先要了解 | 和 >>> ,这个不懂的可以自己百度,很简单。
    n |= n >>> 1;
    n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16;

    首先看这集行有什么作用呢,他就是我了的到一个二进制数,这个二进制数前面都是0,后面都是1,组成。
    比如:00001111。 这个数是十进制15,那么这个数+1的话很容易的就得到了16,也就是2的4次冥。
    那为什么这个算法可以得到这种结构呢?
    让我们来举个例子,因为hashmap最大容量是2的30次方,那么我们就那2的30次方来举例。
    n = 2^30 转换成2进制: 01000000000000000000000000000000

    n |= n >>> 1 : 01100000000000000000000000000000
    n |= n >>> 2      :  01111000000000000000000000000000
    n |= n >>> 4      :  01111111100000000000000000000000
    n |= n >>> 8      :  01111111111111111000000000000000
    n |= n >>> 16     :  01111111111111111111111111111111

    先不管最大位是符号位的问题,2^30通过这样计算以后得到的就是一个2^31-1的数,然后再+1就得到了2^31次了,

    所以这个公式得到的就是n后面的2的n次冥了。

    那么如果传入的n正好是像2^30次一样呢,那么直接用这个方法就会得到2的31次冥了,所以有了开始的
    int n = cap - 1;

    这样我们通过这个方法就肯定能得到2的n次冥了。





        

  • 相关阅读:
    k8s之Controller Manager(七)
    k8s 之apiserver部署(六)
    k8s之etcd集群安装(五)
    k8s 之harbor仓库安装(四)
    k8s 之docker环境部署 (三)
    如何在PPT中同时插入多张图片且每张占一页
    ICMPV6
    整理桌面 | Windows自带工具
    教你在Linux中如何配置网络地址
    解决在gns3中wireshark抓包无法显示和实时刷新问题
  • 原文地址:https://www.cnblogs.com/maylong/p/11232086.html
Copyright © 2011-2022 走看看