本文的目的不是为了阐述位操作的原理,而是发现在工作中有些同学清楚位操作,但是不知道什么时候使用位操作。以下列举两个例子简单说明我们可以使用到位操作的场景,但不一定符合实际业务场景,仅供参考。
1、给40亿个int型的正整数,没排过序,然后再给一个数,如何快速判断这个数是否在那40亿个数当中。(此题根据腾讯的一道面试题改编)
public class A {
long nSize = 4000000000L;
int bSize = (int)(nSize / 8);
byte[] bArray = new byte[bSize]; //正好有40亿个位,每个位代表一个数字
/**
* 将40亿个数放入到数组中,把每个数字对应的位的值由0变为1
* 这里只是为了把数组填满而已
*/
public void init() {
for (long i = 1; i <= nSize; i++) {
if (i % 10 == 0) { //为了让一些数字在bArray中不存在
continue;
}
byte mod = (byte) (i % 8);
int div = (int) (i / 8);
int index = (int)(mod == 0 ? div - 1 : div);
bArray[index] = (byte) (bArray[index] | (1 << mod));
}
}
/**
* 在40亿个数当中查找一个数字是否存在
* 如果n对应的位在bArray的值是1,则表明数字存在
*
* @param n 要查找的数
* @return 如果要查找的数在40亿中存在,返回true,否则返回false
*/
public boolean find(long n) {
byte mod = (byte) (n % 8);
int div = (int) (n / 8);
int index = (int)(mod == 0 ? div - 1 : div);
return (bArray[index] & (1 << mod)) > 0;
}
public static void main(String args[]) {
A a = new A();
a.init();
System.out.println(a.find(111));
System.out.println(a.find(1000));
}
}
2、假设一个订单有三组状态需要记录,分别是付款状态、发货状态、签收状态,我们可以在类里用三个属性来表示(一般来说都是这么做的),这里我们用另外一种方式用一个属性将所有状态表示出来(这么做之前要仔细考虑是否符合业务需求)
public class Order {
//订单状态,将三组订单状态用这个值后三位表示
private byte status = 0x00;
//付款
public void pay() {
this.status |= Status.已付款.getValue();
}
//发货
public void send() {
this.status |= Status.已发货.getValue();
}
//签收
public void receive() {
this.status |= Status.已签收.getValue();
}
//获取已付款状态
public boolean hasPaid() {
return (this.status & Status.已付款.getValue()) > 0;
}
//获取已发货状态
public boolean hasSent() {
return (this.status & Status.已发货.getValue()) > 0;
}
//获取已签收状态
public boolean hasReceived() {
return (this.status & Status.已签收.getValue()) > 0;
}
//main()
public static void main(String args[]) {
Order order = new Order();
order.send();
System.out.println(order.hasPaid());
System.out.println(order.hasSent());
System.out.println(order.hasReceived());
}
}
//订单状态枚举类
enum Status {
已付款((byte)0x01),
已发货((byte)0x02),
已签收((byte)0x04);
private Status(byte b) {
this.value = b;
}
private byte value;
public byte getValue() {
return value;
}
}