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;
}
看代码的那些n
的赋值操作,突然看到有点懵。常见的!= == +=
突然出现这个|=
措手不及。后来突然回想到,这是省略的写法,才想到,其实想表达的意思是n = n | n >>> 1
。所以所有的赋值操作,如果需要进行运算操作的话,都可以简写成运算符=
java
中的整数int
java
中的int类型,是32位
因此普通的1,其实是00000000000000000000000000000001
-1,是11111111111111111111111111111111
其实就是正数1
的补码。最高位为1,标识为负数。
即正数1
:00000000000000000000000000000001
取反
得到反码11111111111111111111111111111110
。
+1,得到补码:11111111111111111111111111111111
也就是-1
带符号位的右移>>
>>
意思就是最高位的符号位不动,往右移动位数
左位移和右位移差不多,因此本次仅说明右位移,左位移自己类比就行。
>>
举例
正数右位移
正数的话,就是往右移动相应的位数,左边补相应的0
System.out.printf("%s%n", 1 >> 1);//result:0
System.out.printf("%s%n", Integer.toBinaryString(1 >> 1));//result:00000000000000000000000000000000省略为0
//分析
//00000000000000000000000000000001 ==> 00000000000000000000000000000000
//往右移动1位,失去了最右边的1,因此变成了31位的0,左边补0,凑齐32位,因此为0
System.out.printf("%s%n", 1 >> 2);//result:0
System.out.printf("%s%n", Integer.toBinaryString(1 >> 2));//result:00000000000000000000000000000000省略为0
//分析
//00000000000000000000000000000001 ==> 00000000000000000000000000000000
//往右移动2位,失去了最右边的01,因此变成了30位的0,左边补00,凑齐32位,因此还是0
System.out.printf("%s%n", 64 >> 1);//result:32
System.out.printf("%s%n", Integer.toBinaryString(64 >> 1));//result:00000000000000000000000000100000省略为100000
//分析
//00000000000000000000000001000000 ==> 00000000000000000000000000100000
//往右移动1位,失去了最右边的0,因此变成了31位的0000000000000000000000000100000,左边补0,凑齐32位,因此为32,即100000
System.out.printf("%s%n", 64 >> 2);//result:16
System.out.printf("%s%n", Integer.toBinaryString(64 >> 2));//result:00000000000000000000000000010000省略为10000
//分析
//00000000000000000000000001000000 ==> 00000000000000000000000000010000
//往右移动2位,失去了最右边的00,因此变成了30位的0,左边补00,凑齐32位,因此为16,即10000
补充:因此可以知道,左移的话,左移1位,这个1就变成了2,左移2位,就变成了4,不再细说`左移`。
负数右位移
负数的话,就是往右移动相应的位数,左边补相应的1
System.out.printf("%s%n", -1 >> 1); //result:-1
System.out.printf("%s%n", Integer.toBinaryString(-1 >> 1));//result:11111111111111111111111111111111
//分析
//11111111111111111111111111111111 ==> 11111111111111111111111111111111
//往右移动1位,失去了最右边的1,因此变成了31位的1,左边补1,凑齐32位,因此还是为-1
System.out.printf("%s%n", -1 >> 2); //result:-1
System.out.printf("%s%n", Integer.toBinaryString(-1 >> 2));//result:11111111111111111111111111111111
//分析
//00000000000000000000000000000001 ==> 00000000000000000000000000000000
//往右移动2位,失去了最右边的11,因此变成了30位的1,左边补11,凑齐32位,因此还是-1
System.out.printf("%s%n", -64 >> 1);//result:-32
System.out.printf("%s%n", Integer.toBinaryString(-64 >> 1));//result:11111111111111111111111111100000
//分析
//11111111111111111111111111000000 ==> 11111111111111111111111111100000
//往右移动1位,失去了最右边的0,因此变成了31位的1111111111111111111111111100000,左边补1,凑齐32位,因此变成了11111111111111111111111111100000,即-32
System.out.printf("%s%n", -64 >> 2);//result:-16
System.out.printf("%s%n", Integer.toBinaryString(-64 >> 2));//result:11111111111111111111111111110000
//分析
//11111111111111111111111111000000 ==> 11111111111111111111111111110000
//往右移动2位,失去了最右边的00,因此变成了30位的111111111111111111111111110000,左边补11,凑齐32位,因此变成了111111111111111111111111110000,即-16
不带符号位的右移>>>
简单理解就是所有的数都当正数来处理
所谓无符号位右移,类似有符号位的右移,只不过唯一的区别就是,移动的位数,左边需要补齐的,全部用0
补齐。
>>>
举例
正数无符号右位移
System.out.printf("%s%n", 1 >>> 1); //result:0
System.out.printf("%s%n", Integer.toBinaryString(1 >>> 1));//result:0
//分析
//00000000000000000000000000000001 ==> 00000000000000000000000000000000
//往右移动1位,失去了最右边的1,因此变成了31位的0,左边补0,凑齐32位,因此还是0
System.out.printf("%s%n", 1 >>> 2); //result:0
System.out.printf("%s%n", Integer.toBinaryString(1 >>> 2));//result:0
//分析
//00000000000000000000000000000001 ==> 00000000000000000000000000000000
//往右移动2位,失去了最右边的01,因此变成了30位的0,左边补00,凑齐32位,因此还是0
System.out.printf("%s%n", 64 >>> 1);//result:32
System.out.printf("%s%n", Integer.toBinaryString(64 >>> 1));//result:100000
//分析
//00000000000000000000000001000000 ==> 00000000000000000000000000100000
//往右移动1位,失去了最右边的0,因此变成了31位的0000000000000000000000000100000,左边补0凑齐32位,因此变成了00000000000000000000000000100000,即32
System.out.printf("%s%n", 64 >>> 2);//result:16
System.out.printf("%s%n", Integer.toBinaryString(64 >>> 2));//result:10000
//分析
//00000000000000000000000001000000 ==> 00000000000000000000000000010000
//往右移动2位,失去了最右边的00,因此变成了30位的000000000000000000000000010000,左边补00,凑齐32位,因此变成了000000000000000000000000010000,即16
负数的无符号右位移
参考上面 java
中的整数 int
,负数的表示方法,可以更好理解下面的负数位移操作
System.out.printf("%s%n", -1 >>> 1);//result:2147483647
System.out.printf("%s%n", Integer.toBinaryString(-1 >>> 1));//result:1111111111111111111111111111111
//分析
//11111111111111111111111111111111 ==> 01111111111111111111111111111111
//往右移动1位,失去了最右边的1,因此变成了31位的1,左边补0凑齐32位. 因此变为正数的2147483647
System.out.printf("%s%n", -1 >>> 2);//result:1073741823
System.out.printf("%s%n", Integer.toBinaryString(-1 >>> 2));//result:111111111111111111111111111111
//分析
//11111111111111111111111111111111 ==> 00111111111111111111111111111111
//往右移动2位,失去了最右边的11,因此变成了30位的1,左边补00凑齐32位。因此变为正数的1073741823
System.out.printf("%s%n", -64 >>> 1);//result:2147483616
System.out.printf("%s%n", Integer.toBinaryString(-64 >>> 1));//result:1111111111111111111111111100000
//分析
//11111111111111111111111111000000 ==> 01111111111111111111111111100000
//往右移动1位,失去了最右边的0,因此变成了31位的1111111111111111111111111100000,左边补0,凑齐32位,因此变成了正数的2147483616
System.out.printf("%s%n", -64 >>> 2);//result:1073741808
System.out.printf("%s%n", Integer.toBinaryString(-64 >>> 2));//result:111111111111111111111111110000
//分析
//11111111111111111111111111000000 ==> 00111111111111111111111111110000
//往右移动2位,失去了最右边的00,因此变成了30位的111111111111111111111111110000,左边补00,因此变成了正数的1073741808