java 位运算
- 2020 年 10 月 23 日
- 筆記
| (位或运算)
在运算位或中,两个数值的二进制码中只要对应位中一个位1那么当前对应位运算结果位1
java中一个int字节占4位,一位8个字节码
15 二进制码 ---》ob 0000 0000 0000 0000 0000 0000 0000 1111
25 二进制码 ---》ob 0000 0000 0000 0000 0000 0000 0001 1001
(进行位或运算)
ob 0000 0000 0000 0000 0000 0000 0000 1111
| (位或运算符)
ob 0000 0000 0000 0000 0000 0000 0001 1001
=ob 0000 0000 0000 0000 0000 0000 0001 1111(对应位其中一个为1则结果为1)
& (位与运算)
在运算位与中,两个数值的二进制码中对应位两个数值都为1则结果为1否则结果为0
30 二进制码---》 ob 0000 0000 0000 0000 0000 0000 0001 1110
35 二进制码---》 ob 0000 0000 0000 0000 0000 0000 0010 0011
(进行位与运算)
ob 0000 0000 0000 0000 0000 0000 0001 1110
&(位于运算符)
ob 0000 0000 0000 0000 0000 0000 0010 0011
=ob 0000 0000 0000 0000 0000 0000 0000 0010(对应为两个都为1则结果为1)
^(位异或运算)
在位异或运算中,两个数值的二进制码中对位的两个数值相等则结果为0,不等结果为1
40 二进制码---》 ob 0000 0000 0000 0000 0000 0000 0010 1000
45 二进制码---》 ob 0000 0000 0000 0000 0000 0000 0010 1101
(进行异或运算)
ob 0000 0000 0000 0000 0000 0000 0010 1000
^
ob 0000 0000 0000 0000 0000 0000 0010 1101
=ob 0000 0000 0000 0000 0000 0000 0000 0101(对应位相等结果为0,不等结果为1)
计算机中负数的表示
在java中所有操作的数值都是数据的补码,正数的二进制源码、反码,补码都是一样的
负数的补码 (最高位为符号位)
-6 源码 ob 1000 0000 0000 0000 0000 0000 0000 0110
反码 ob 1111 1111 1111 1111 1111 1111 1111 1001
补码(在其反码上+1)
ob 1111 1111 1111 1111 1111 1111 1111 1010
所以在java中-6的存储的格式为 ob 1111 1111 1111 1111 1111 1111 1111 1010
<<(位左移运算)
在位左计算中,就是将数值的二进制补码向左移两位(左移操作会使数值增大————2的移动位数的次方增长)
正数左移
10<<2
ob 0000 0000 0000 0000 0000 0000 0000 1010
2<<(左移两位)
ob 0000 0000 0000 0000 0000 0000 0010 1000
= 40
负数左移
-10<<2
ob 1000 0000 0000 0000 0000 0000 0000 1010(源码)
ob 1111 1111 1111 1111 1111 1111 1111 0101(符号位不管 反码)
ob 1111 1111 1111 1111 1111 1111 1111 0110(补码)
2<<(左移两位)
ob 1111 1111 1111 1111 1111 1111 1101 1000(得到左移后的补码)
- 1
ob 1111 1111 1111 1111 1111 1111 1101 0111(补码减一得到反码)
ob 1000 0000 0000 0000 0000 0000 0010 1000(得到源码)
=-40
>>(位右移运算)
在位右移运算中,就是将数值的补码向右移动相应的位数,左边空出来的位数用符号位填充(右移操作会使操作数缩小————2的右移位数的次方数缩小)
正数右移
20>>2
ob 0000 0000 0000 0000 0000 0000 0001 0100
>>2(右移两位)
ob 0000 0000 0000 0000 0000 0000 0000 0101
=5
负数右移
-30>>1
ob 1000 0000 0000 0000 0000 0000 0001 1110(源码)
ob 1111 1111 1111 1111 1111 1111 1110 0001 (符号位不管 反码)
ob 1111 1111 1111 1111 1111 1111 1110 0010(补码)
>>1
ob 1111 1111 1111 1111 1111 1111 111 0001(计算后的补码)
- 1
ob 1111 1111 1111 1111 1111 1111 1111 0000(计算后的补码-1得到计算后的反码)
ob 1000 0000 0000 0000 0000 0000 0000 1111
=-15
>>>(无符号右移)
无符号右移,就是将数值的补码向右移动相应的位数,左边空出的用0补,正数和右移一样,而负数是不管符号位,也就是所一个负数经过无符号右移会转换位一个正数
-15>>>2
ob 1000 0000 0000 0000 0000 0000 0000 1111
ob 1111 1111 1111 1111 1111 1111 1111 0000
ob 1111 1111 1111 1111 1111 1111 1111 0001
>>>2(无符号右移)
ob 0011 1111 1111 1111 1111 1111 1111 1100(正数的补码,反码,源码一样)
=1073741820
实例讲解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;
}
如果传如15即cap=15
1、n=15-1 =14;
14二进制码 --》ob 0000 0000 0000 0000 0000 0000 0000 1110
2、n|= n>>>1
ob 0000 0000 0000 0000 0000 0000 0000 1110
>>> 1 (无符号右移1位)
ob 0000 0000 0000 0000 0000 0000 0000 0111
|
ob 0000 0000 0000 0000 0000 0000 0000 1110
=ob 0000 0000 0000 0000 0000 0000 0000 1111
n=15
3、n |= n >>> 2;
ob 0000 0000 0000 0000 0000 0000 0000 1111
>>>2
ob 0000 0000 0000 0000 0000 0000 0000 0011
|
ob 0000 0000 0000 0000 0000 0000 0000 1111
=ob 0000 0000 0000 0000 0000 0000 0000 1111
n=15
4、 n |= n >>> 4;
ob 0000 0000 0000 0000 0000 0000 0000 1111
>>>4
ob 0000 0000 0000 0000 0000 0000 0000 0000
|
ob 0000 0000 0000 0000 0000 0000 0000 1111
=ob 0000 0000 0000 0000 0000 0000 0000 1111
n=15
后面就不用算了呀,ob 0000 0000 0000 0000 0000 0000 0000 1111这个不管向右移大于4位后。就已经全部为0了
在与ob 0000 0000 0000 0000 0000 0000 0000 1111 或运算一下还是这个是ob 0000 0000 0000 0000 0000 0000 0000 1111
最后得出当传入初始化数值为15时,扩容阈值为16.当然这个值是在初始hashmap是传入了散列表参数时。
如果是默认长度,那么是散列表的默认长度*0.75