BitSet是位操作的对象,值只有0或1即false和true,最常用的地方是用户、系统开关,原理是内部维护了一个long数组,初始只有一个long,所以BitSet最小的size是64,当随着开关越来越多,会动态扩充,最终内部是由N个long来存储,这些对操作都是透明的。
为什么要将BitSet和Byte数组进行互转呢,场景,假设我们为每个用户对象设了一个开关字段对应的mysql表是blob类型,里面存储了用户很多的开关,如果在64个开关以内完全可以用long来存储,但是考虑到扩展性,自己来维护N个long还是有难度的,所以利用BitSet对象来存储。BitSet已经实现了java的Serializable接口,可以直接序列化,但是考虑到跨语言,所以不能直接用java序列化,需要将BitSet转成Byte数组,读取时在将Byte数组转为BitSet对象。
import java.util.Arrays;
import java.util.BitSet;
public class BitSetConvert {
public static byte[] bitSet2ByteArray(BitSet bitSet) {
byte[] bytes = new byte[bitSet.size() / 8];
for (int i = 0; i < bitSet.size(); i++) {
int index = i / 8;
int offset = 7 - i % 8;
bytes[index] |= (bitSet.get(i) ? 1 : 0) << offset;
}
return bytes;
}
public static BitSet byteArray2BitSet(byte[] bytes) {
BitSet bitSet = new BitSet(bytes.length * 8);
int index = 0;
for (int i = 0; i < bytes.length; i++) {
for (int j = 7; j >= 0; j--) {
bitSet.set(index++, (bytes[i] & (1 << j)) >> j == 1 ? true
: false);
}
}
return bitSet;
}
public static void main(String[] args) {
BitSet bitSet = new BitSet();
bitSet.set(0, true);
bitSet.set(10, true);
//将BitSet对象转成byte数组
byte[] bytes = bitSet2ByteArray(bitSet);
System.out.println(Arrays.toString(bytes));
//在将byte数组转回来
bitSet = byteArray2BitSet(bytes);
System.out.println(bitSet.get(0));
System.out.println(bitSet.get(10));
}
}