zoukankan      html  css  js  c++  java
  • ConcurrentHashMap之tableSizeFor()方法透析(位运算运用)

     
    ConcurrentHashMap和HashMap有如下方法
    inttableSizeFor(int c)
    //功能:输入低于最大容量的数c,返回大于等于且最接近c的2的幂次数。
    源码:
     
    private static final int MAXIMUM_CAPACITY = 1 << 30;
     
    private static final int tableSizeFor(int c) {
        int n = c - 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;
    }
    解释/总结1:符号>>:右移n位相当于除以2的n次方。符号<<:左移n位就相当于乘以2的n次方。 >>>无符号右移:"零扩展",无论正负,左边都补0。|符号,按位或,使用二进制计算:0|1=1,0|0=0,1|1=1
    2:设c=010001101,即141.
    执行:先减1,n=140--转为2进制---010001100  
        n |= n >>> 1------无符号右移一位,左边补0
        001000110 |       |操作
        010001100   
    ->n=011001110
        n |= n >>> 2------同上
        011001110 | 
        000110011     
    ->n=011111111=255
    最高位1后面已经均为1,后面再执行|操作n不会发生变化了,
    最后n=255,返回n+1即256。可以看出该算法通过几次无符号右移和|操作会让最高位的1后面的位全变为1。
    3:在使用位运算之前减1是必要的,否则对于c=16,最后就会得到32.实际需求应当返回16.
    4:为什么最后写到n|n >>> 16?我们知道int范围在-2^31~2^31-1,因此对于int最大的2次幂数为2^30,这也就是MAXIMUM_CAPACITY的值。c超过这个值就会返回MAXIMUM_CAPACITY。
    而这边代码中一共右移了1+2+4+8+16=31位,因此可以保证高位1以下的低位都会变成1.
    5:如果c是负数,那么结果如何
    int c=-100;
    c|= c >>> 1;
    System.out.println( c );
    c|= c >>> 2;
    System.out.println( c );
    c|= c >>> 4;
    System.out.println( c );
    c|= c >>> 8;
    System.out.println( c );
    结果:
    -34
    -1
    -1
    -1
    运算过程中|操作后使用补码运算同样会不断的将0变成1;最后就会变成111111111111111111...=-1
     
    实践发现如果传入负数最后n最大会变成-1,而上述算法中(n < 0) ? 1会返回1,不会有异常.

     
    6:总结:这个算法主要是对位运算的运用.这里我总结一下位运算的运用
     |按位或运算:可以将指定的低位从0变成1,如a|0111 (2进制),这样就可以将低3位 置为1.
     ^异或运算:这个运算是相同的位得0,不同的得1. 它可以用来反转低位得值.如
    1001^0111(2进制) =1110,后三位反转了.还有之前学过的可以用来交换a,b: a=a^b;b=b^a;a=a^b;
    &按位与操作:可以用来保留后n位:如:010101&0111=000101这样保留后三位不变,其余为0.
    <<左移:左移n等同于乘以2的n次方
    >>右移:右移n等同于除以2的n次方,正数右移高位补0,负数右移高位补1
    >>>无符号右移:无论是正数还是负数,高位都补0。
    (左移右移时需要注意范围)
     
    应用:
    //判断两个int类型数是否同正负:
    //只要看高位的数是不是不同即可
    public static boolean SameSymbolInt(int a,int b){
        return ((a >> 31) ^ (b >> 31)) == 0;
    }
  • 相关阅读:
    OpenStack Pike超详细搭建安装文档 LinuxBridge版
    OpenStack Ocata 超详细搭建文档
    此博客关闭,转到 https://www.justbio.wang/
    面向对象03 封装 反射 内置方法
    面向对象02 继承
    面向对象01
    awk使用说明
    MySQL优化聊两句
    Redis分布式集群几点说道
    Nginx最大客户连接数算法一些遐想
  • 原文地址:https://www.cnblogs.com/yang4869/p/11078816.html
Copyright © 2011-2022 走看看