你所不知道的二进制实战技巧

点击上方“程序员小灰”,选择“置顶公众号”

有趣有内涵的文章第一时间送达!



本文转载自公众号  匠心零度

说在前面

看过稍微底层点的源码的人应该都会了解、熟悉里面多多少少会碰到二进制相关操作,本篇准备写一些二进制实战技巧相关内容。

主题

  • 判断一个数是否是2的幂次方的方法。

  • 操作位代表类型。

  • 非2的幂次方转换为2的幂次方。

判断一个数是否是2的幂次方的方法

如果该数是无符号整数,可以使用:

private static boolean isPowerOfTwo(int val) {
     return (val & (val-1)) == 0;
}

如果一个数是2的n次方,那么这个数用二进制表示时其最高位为1,其余位为0,(val-1)和val都错开了0和1,那么&一定是0。

如果该数是无符号整数,也可以使用:

private static boolean isPowerOfTwo(int val) {
     return (val & -val) == val;
}

如果一个数是2的n次方,那么这个数用二进制表示时其最高位为1,其余位为0,(val & -val)就是获取最右1的位,那么如果和val等于就是了。

扩展下,如何判断一个无符号数是2的n次方-1

private static boolean isPowerOfTwoLoseOne(int val) {
     return (val & (val+1)) == 0;
}

理由其实和上面类似了。

操作位代表类型

JDK SelectionKey有四种操作类型,分别为:

OP_READ = 1 << 0
OP_WRITE = 1 << 2
OP_CONNECT = 1 << 3
OP_ACCEPT = 1 << 4

由于只有四种网络操作类型,所以用4 bit就可以表示所有的网络操作位,由于JAVA语言没有bit类型,所以使用了整形来表示,每个操作位代表一种网络操作类型,分别为:0001、0010、0100、1000,这样做的好处是可以非常方便的通过位操作来进行网络操作位的状态判断和状态修改,提升操作性能。

说明:依稀记得RocketMQ里面好像也是类似,有一个当磁盘空间大于90%的时候不给写权限就是类似控制的,后续分析RocketMQ源码的时候会进行说明。

非2的幂次方转换为2的幂次方

在jdk很多集合框架里面,不知道你们还发现了,集合的大小都会是2的幂次方,哈哈,所以就引出了下面的话题。

 int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ?
                  MAXIMUM_CAPACITY :


   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;
   }

实例化ConcurrentHashMap时带参数时,会根据参数调整table的大小,确保table的大小总是2的幂次方,调用tableSizeFor的时候每次返回的都是大于等于离该数最近的2的幂次方的数。比如调用tableSizeFor传入c为151的时候 比151大的2的幂次方的数就是256了,核心就是上面的位运算操作。

刚刚上面是求一个数离它最近的大于等于2的幂次方的数,如果求小于等于2的幂次方的数,我们应该怎么办呢?

 private static final int tableSizeFor(int n) {
       n |= n >>> 1;
       n |= n >>> 2;
       n |= n >>> 4;
       n |= n >>> 8;
       n |= n >>> 16;
       return  n-(n>>1);
   }

说明:由于集合的大小都会是2的幂次方,那么求table大小的0.75倍的时候,可以使用(n - (n >>> 2))即可,取模的时候,可以使用hash & 0x7FFFFFFF来进行操作即可。

结束语

上面的都是零度发现的一些实战,如果你发现什么更好的二进制实战,欢迎在留言区积极留言评论。!!!




—————END—————




喜欢本文的朋友们,欢迎长按下图关注订阅号程序员小灰,收看更多精彩内容


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值