大数据处理利器之Bitmap以及java实例

什么是Bitmap?

所谓Bitmap,字面意思即为位映射,即用一个bit来标记某个数字对应的值。通常用于海量数据查询、去重、过滤等场景,大大节省查询时间和存储空间。

场景举例

有这样一道面试题,现有10亿个随机整数,32位机器内存1G?那我们可以算下,一个int占4个字节,即我们需要4000000000/(1024×1024×1024)≈3.7G,显然不够。那么使用bitmap呢?1bit为8位,所以每个byte记录8bit信息,也就是可以表示8个数,占据4000000000/(1024×1024×1024×8)≈465MB,空间大大节省。时间复杂度O(n)。


image.png

每个bit上我们可以用0或者1来表示这个数字是否存在。比如125这个数字,它会落在哪个字节上呢?125/8=15,落在第15个字节上,那我们应该把它存在哪个bit上呢?125%8=5,落在第5个bit上,即我们将下标为4的标记为1,此时二进制数为00001000;如果再来一个数字123呢?同样125/8=15,落在第15个字节上,125%8=3,落在第3个bit上,我们将下标为2 的标记为1,此时的二进制数为00101000,查询如果bit位为1,则存在。

java 代码示例

public class BitMap {

    public static final int DEFAULT = 1024*1024*1024;

    public int size;

    private byte[] map;

    public BitMap() {
        this.size = DEFAULT;
        this.map = new byte[size];
    }

    public BitMap(int size) {
        this.size = size;
        this.map = new byte[size];
    }

    public void set(int val) {
        if (val < 0) {
            throw new RuntimeException("need Positive integer");
        }
        //等价于val/8得到所在的第几个字节里,即位桶
        int seg = val >> 3;

        //等价于val%8获取余数,即位于上面求得所在位桶的第几位
//        int mod = val & (0x07);

        map[seg] |= 0x01 << (val & (0x07));
    }


    public boolean exist(int val) {
        if (val < 0) {
            throw new RuntimeException("need Positive integer");
        }
        //计算位于第几个桶位
//        int seg = val >> 3;
        //位于上面求得所在位桶的第几位
//        int mod = val & 7;

        return ((map[val >> 3] >> (val & 7)) & 0x01) == 0x01;
    }

}

那下面来说下代码的实现细节和详解。
例如数字125,存储为byte[15],值为2的5次方 = 32,二进制00001000,再存储123,存储为byte[15],值为24+22=20,二进制为00101000,即为00001000和00100000进行或运算,即为代码中的map[seg] |= 0x01 << (val & (0x07))。

当查询的时候,我们只需对比位桶上的下标位是否为1,例如我们查询123是否存在
image.png

即代码中((map[val >> 3] >> (val & 7)) & 0x01) == 0x01。

运行验证

public static void main(String[] args) {

        BitMap bitMap = new BitMap();

        int[] array = new int[20000000];
        Random random = new Random();


        for (int i = 0; i < array.length; i++) {
            array[i] = random.nextInt(5000000);
        }

        for (int i = 0; i < array.length; i++) {
            bitMap.set(array[i]);
        }
        long start = System.currentTimeMillis();

        for (int a : array) {
            if (!bitMap.exist(a)) {
                System.out.println("not exist");
            }
        }
        System.out.println("bitmap时间=" + (System.currentTimeMillis() - start));
    }

运行结果:


image.png

2千万条数据循环遍历查询时长仅50ms。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容