1与运算(&)
0 & a = 0
1 & a = a
a表示0或者1任意值。
(1)与运算判断奇偶
能被2整除的数是偶数(二进制的最后一位是0),结合与运算的性质不难得出:
a & 1 = 0 偶数
a & 1 =1 奇数
(2)与运算+异或求平均值
有int类型变量x、y,现需要求其平均值。
首先要求x+y的和,再除以2,但是有可能x+y的结果会超过int的最大表示范围(这里强行加入位运算,x和y分别除2再相加也不会越界啦)
(x&y)+((x^y)>>1)
&运算:相当于十进制 相同位做加法的1/2
0101 & 0011 结果:二进制0001 十进制 (2^0 +2^0)/2 这里的"^"代表次幂
(3)HashMap源码中与运算的妙用
对于任意给定的对象,只要它的 hashCode() 返回值相同,那么程序调用 hash(int h) 方法所计算得到的 hash 码值总是相同的。我们首先想到的就是把hash值对数组长度取模运算,这样一来,元素的分布相对来说是比较均匀的。但是,“模”运算的消耗还是比较大的,在HashMap中是这样做的:
static int indexFor(int h, int length) { return h & (length-1); }
HashMap的底层数组的长度总是 2 的 n 次方,这是HashMap在速度上的优化。为什么呢?
举个例子,若hashMap数组长度是15(1111),那么位置计算是h&(15-1),14(1110)的最后一位是0所以h的最后一位与操作永远是0,这样的后果是0001,0011,0101,1001,1011,1101这些尾数为1的空间永远不会放置数据,造成极大的空间浪费。
而当底层数组的长度总是 2 的 n 次方时,h & (length-1)等价与h% (length-1),但是效率比前者要高很多。
2或运算(|)
0 | a = a
1 | a = 1
a表示0或者1任意值。
|运算:相当于十进制 相同位做加法的1/2与不同位做加法求和
0101 | 0011 结果:二进制0111 十进制 (2^0 +2^0)/2 +(2^2 +2^1)
3非运算(~)
~运算规则是按位取反
~(0011)= 1100