程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算就是直接对整数在内存中的二进制位进行操作,它的效率会比编程语言的算术运算效率高。
常见的位运算
常见的位运算符见表格中,主要有&(与)、|(或)、^(异或)、<<(左移位)和 >>(右移位)。
&运算
&运算,称作 与运算,对于同为1的列运算结果为1,其余情况均为0。
25&15
25二进制表示为 11001,15二进制表示为1111,按位&运算,对于同为1的位置取结果为1,其余均为0,最终结果为01001,01001十进制为9。
System.out.println(Integer.toBinaryString(25));
System.out.println(Integer.toBinaryString(15));
System.out.println(25&15);
执行代码,可以得到结果 9
用途,利用&运算同1则1的特性,可以判断奇偶数,任何奇数的最后一位均为1,偶数则为0。任何一个数字num:num&1 = 1,则说明num的最后一位为1,其为奇数;若num&0 = 0,则说明num的最后一位为0,其为偶数。
System.out.println(25&1);
System.out.println(24&0);
运算结果为 1 和 0
|运算
|运算,称作或运算,对于同为0的值运算结果为0,其余均为1
25|15
25二进制表示为 11001,15二进制表示为1111,按位|运算,对于同为0的位置取结果为0,其余均为1,最终结果为11111,11111十进制为31。
System.out.println(25|15);
执行结果为 31
^运算
^运算称为异或运算,如果a、b两个值不相同,则异或结果为1。如果a、b两个值相同,异或结果为0。
25^15
25二进制表示为 11001,15二进制表示为1111,按位^运算,对于不同的位取1,其余均为0,最终结果为10110,10110十进制为22。
异或运算jdk源码中,在HashMap取hash值的时候有使用
对hashCode值无符号右移16位,然后与hashCode值本身做异或操作,以获取一个比较准确的hash值。
<<运算
a << b 表示把a转为二进制后左移b位(在后面添b个0),相当于乘以2的b次幂
25 << 2 ,25二进制表示为11001,左移位两次后,相当于给二进制数字右边补两个0,为1100100,换算下来为100
System.out.println(25<<2);
基于移位运算的高效性,Java代码中不少使用移位运算的地方,HashMap源代码中
默认容量 1<<4 即初始容量16;hashmap最大容量 1<<30。
/**
* The default initial capacity - MUST be a power of two.
*/
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
/**
* The maximum capacity, used if a higher value is implicitly specified
* by either of the constructors with arguments.
* MUST be a power of two <= 1<<30.
*/
static final int MAXIMUM_CAPACITY = 1 << 30;
hashMap扩容时,使用移位运算,增加一倍的容量
>>运算
a >> b 表示把a转为二进制后右移b位(去掉末b位),相当于除以2的b次幂。
25>>2 ,25的二进制表示为11001,右移两位,相当于去掉末尾两位,结果为110,二进制110转换为10进制为6。
右移jdk源码中也有使用,例如ArrayList的扩容部分
ArrayList在扩容时,新容量newCapacity = oldCapacity + (oldCapacity >> 1) ,oldCapacity >> 1 即对旧容量右移1位操作,对旧容量除以2,newCapacity 就为 1.5个oldCapacity。