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;
    }
  • 相关阅读:
    使用某些 DOCTYPE 时会导致 document.body.scrollTop 失效
    VB.NET 笔记1
    知识管理系统Data Solution研发日记之一 场景设计与需求列出
    知识管理系统Data Solution研发日记之五 网页下载,转换,导入
    折腾了这么多年的.NET开发,也只学会了这么几招 软件开发不是生活的全部,但是好的生活全靠它了
    分享制作精良的知识管理系统 博客园博客备份程序 Site Rebuild
    知识管理系统Data Solution研发日记之四 片段式数据解决方案
    知识管理系统Data Solution研发日记之二 应用程序系列
    知识管理系统Data Solution研发日记之七 源代码与解决方案
    知识管理系统Data Solution研发日记之三 文档解决方案
  • 原文地址:https://www.cnblogs.com/yang4869/p/11078816.html
Copyright © 2011-2022 走看看