BitMap的简单实现

167 阅读1分钟

思路

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));
        }
    }
}

结尾

这只是简单实现了下,如要存储负数可另外开辟一个数据,存储该值的绝对就可以,当然更完善一点可以进行扩容等操作。