思路
1byte = 8bit最多表示0 ~ 7 位数,如果需要存储大于7的数可以设计一个byte数组,根据需要表示数据对8取余可计算byte数组下标 eg: 99/8 = 99 >> 3 = 12 即 99该存储在 byte[12]中。具体需要存在byte哪一位则只需要对8取模就可以得到: 99%8 = 3 (往后数第三位,以为8为2的次方 %8可表示为 &(8-1))二进制表示 00001000 具体代码实现如下文。
代码
package cn.gw.example;
/**
* @author gaowu
* @date 2022/3/5 16:31
*/
public class BitMap {
private byte[] data;
public BitMap put(int value) {
checkVal(value);
// 获取当前value所在的data下标
int point = value >> 3;
//byte : 1 1 1 1 1 1 1 1
//index: 0 1 2 3 4 5 6 7
//val : 7 6 5 4 3 2 1 0
// eg: 99/8 = 12 则在 data[12] 99%8 = 3 val = 3 index = 4 所以需要在data[12]下表为4的值变为1
// 00001000 (新增的值)
// |
// 00100001 (original value)
//= 00101001 (new value)
// index = 7 - value % 8
// 对于2次方取模相当于 &(n-1)
byte b = (byte) (1 << value & (8 - 1));
data[point] = (byte) (data[point] | b);
return this;
}
public BitMap remove(int value) {
checkVal(value);
//~00001000
// =
// 11110101
//&
// 00101001
//=00100001
data[value >> 3] = (byte) (data[value >> 3] & ~(1 << value & (8 - 1)));
return this;
}
public boolean get(int value) {
checkVal(value);
// 如果index 值为 0 则 相当于0|1 否则相当于 1|1
return data[value >> 3] == (byte) (data[value >> 3] | 1 << value & (8 - 1));
}
private void checkVal(int value) {
if (value < 0) throw new RuntimeException("Value is less than 0 ");
}
BitMap(int cap) {
this.data = new byte[Math.max(cap, 16 >> 3) >> 3];
}
public static void main(String[] args) {
BitMap bitMap = new BitMap(1000);
for (int i = 0; i < 16; i++) {
bitMap.put(i);
}
for (int i = 0; i < 160; i++) {
System.out.println("i = " + i + bitMap.get(i));
}
}
}
结尾
这只是简单实现了下,如要存储负数可另外开辟一个数据,存储该值的绝对就可以,当然更完善一点可以进行扩容等操作。