Java中的位运算

Java中的位运算

Java提供了多种位运算,包括 左移( << )、右移( >> ) 、无符号右移( >>> ) 、位与( & ) 、位或( | )、位非( ~ )、位异或( ^ ),除了 ~ 为一元操作符,其他都为二元操作符。

左移和右移

什么是左右移操作,产生的结果是什么

使用 符号 << 对数字产生的影响就是左移,同理右移。下面通过例子来看左移(右移)的结果:

ArrayList 中,使用了grow()方法进行List的扩容操作,其实,在grow()方法内部就使用到了右移操作。

1
2
3
4
5
6
7
8
9
10
11
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}

grow() 函数的作用就是对 List 进行倍数的扩容,这个倍数就是 x + x >> 1 ,具体产生的结果用主函数进行测试。

1
System.out.println(10+(10>>1));

产生的结果为15.也就是说 10>>1的结果为5.那么计算过程是什么样的呢,才会产生这样的结果?

转化为二进制

对位的运算,第一步一定是先转化为二进制,再对二进制进行计算。

例子中的 10 转化为二进制为:

0000 0000 0000 0000 0000 0000 0000 1010

进行为运算

如果是左移,则在右侧补0,同理如果是右移,则在左侧补0。

比如上面的 10>>1 , 右移一位,则在左侧补一个0。

结果为 ...... 0101 结果为 5

如果 10<<1 ,左移一位,则在右侧补一个0

结果为 ......1 0100 结果为 20

无符号左移右移

负数以原码的补码形式表达,如果是负数时,比如 -10 ,转化为二进制就是

1111 1111 1111 1111 1111 1111 1111 1011

也就是高位为1,与正数相反,同理,在进行移动时,也需要将原来的补0,调整为补1;

如 -10>>1,右移一位,左侧补1

1......1101 ,结果为 -5

无符号则始终补0;

综上:

  1. 转化为二进制
  2. 正数反向补0
  3. 负数反向补1
  4. 无符号反向补0

位与(&)

在HashMap中进行put元素的时候,会通过 putVal() 方法进行实际的计算和添加。

1
2
3
4
5
6
7
8
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
// 使用 (n-1)&hash 查找位置是否已经被占用
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);

这里使用 & 的作用其实是为了保证 hash 的值不超过范围。数组具有2的幂数长度,以用&替换昂贵的取模运算。

运算规则:第一个数的的第n位和第二个数的第n位如果都是1,那么结果的第n为也为1,否则为0 简化描述规则:同一为一,否则为零

5转换为二进制:0000 0000 0000 0000 0000 0000 0000 0101

3转换为二进制:0000 0000 0000 0000 0000 0000 0000 0011

结果:0000 0000 0000 0000 0000 0000 0000 0001

转化为10进制为 1

可以作用为关闭(屏蔽)特定位的手段

位或(|)

运算规则:第一个数的的第n位于第二个数的第n位 只要有一个是1,那么结果的第n为也为1,否则为0. 简化规则描述: 有一则一,否则为零

5转换为二进制:0000 0000 0000 0000 0000 0000 0000 0101

3转换为二进制:0000 0000 0000 0000 0000 0000 0000 0011

结果:0000 0000 0000 0000 0000 0000 0000 0110

转化为10进制为 7

可以作为将特定位置为1的手段

异或(^)

运算规则:第一个数的的第n位于第二个数的第n位 相反,那么结果的第n为也为1,否则为0,简化规则描述: 相反为一,否则为零

5转换为二进制:0000 0000 0000 0000 0000 0000 0000 0101

3转换为二进制:0000 0000 0000 0000 0000 0000 0000 0011

结果:0000 0000 0000 0000 0000 0000 0000 0110

转化为二进制为 7

  1. 按位“异或”运算可以使特定的位取反
  2. 直接交换两个变量的值
1
2
3
a^=b
b^=a
a^=b

这样a的值与b的值就形成了互换。

-------------本文结束感谢您的阅读-------------

本文标题:Java中的位运算

文章作者:NanYin

发布时间:2020年03月28日 - 12:03

最后更新:2020年03月28日 - 17:03

原始链接:https://nanyiniu.github.io/2020/03/28/%E4%BD%8D%E8%BF%90%E7%AE%97/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。