程序员必须掌握的位运算,因为...

 点击上方↑↑↑“Java后端技术栈”关注我们

背景

HashMap源码中有过这么一段代码

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

如果你不会位运算的话,这段代码基本上是看不懂的。

什么是位运算?

计算机在底层使用的是二进制补码进行运算。对应的二进制位进行操作,计算机只识别0和1 。

位运算有什么好处?

巧妙的使用位运算可以大量减少运行开销,优化算法。

Java中支持哪些位运算?

使用案例

复合赋值运算符

位运算符与赋值运算符结合,组成新的复合赋值运算符,它们是:

  • &= 例:a&=b 相当于 a=a&b

  • |= 例:a|=b 相当于 a=a|b

  • >>= 例:a>>=b 相当于 a=a>>b

  • <<= 例:a<<=b 相当于 a=a<<b

  • ^= 例:a^=b 相当于 a=a^b

不同长度的数据进行位运算

如果两个不同长度的数据进行位运算时,系统会将二者按右端对齐,然后进行位运算。

以“与运算”为例说明如下:

我们知道在 C 语言中 long 型占 4 个字节,int 型占 2 个字节,如果一个 long 型数据与一个 int 型数据进行“与运算”,右端对齐后,左边不足的位依下面三种情况补足。

  • 如果整型数据为正数,左边补 16 个 0  

    例如:long a=123,int b=1,计算 a&b

  • 如果整型数据为负数,左边补 16 个 1

    例如:long a=123,int b=-1,计算 a&b

  • 如果整形数据为无符号数,左边也补 16 个 0

    例如:long a=123,unsigned intb=1,计算 a&b

回到本文最前面的那段代码

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

参数 cap 的值肯定大于 0,故 n 大于等于 0 ,假设 n = 0,经过右移之后,依旧为 0 ,0 与 0 异或依旧为 0 ,通过 return 语句的 n+ 1 计算得 1,即 2 的 0 次幂。

当 n 大于 0 时,n 的二进制位肯定会有位的值为 1,即 001xx..xx 的形式,接着,对 n 右移 1 位得 0001xx..xx,再进行位或,由于 1 与 0 或 1 异或结果都为 1,所以结果必为 0011xx..xx 的形式。以此类推,位移 2 位、4 位、8 位、 16 位,最终该算法能让最高位的 1 后面的所有位全变为 1。

下面用一张图举例说明一下:

该算法的最后再让结果值 n + 1,所得即为 2 的整数次幂。为了让结果使结果大于等于参数 cap,在算法开始时,令 cap - 1。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值