zoukankan      html  css  js  c++  java
  • BitMap 初体验

    前言

    给你一台 4G 内存的机器,一组 20 亿个无序正整数,如何快速地判断一个正整数 N 是否在这组数字中?

    这貌似是一道面试题,大致算一下20亿个整数需要占用的内存:
    java中int类型占4个字节,20亿 * 4 / (1024 * 1024 * 1024) ≈ 7.45G

    BitMap的概念

    简单的说,就是用一个bit位来表示一个特定的意义。比如我们有一个长度为8的bit数组,数组的第一个元素表示0是否存在,数组的第二个元素表示1是否存在。。。那么:
    00000010代表1存在;
    01000010代表1和6存在;
    。。。

    但是一个长度为8的bit数组只能表示7是否存在。如果我们想表示10是否存在呢?那么就需要一个长度为11的bit数组。

    数据结构

    从上面我们可以得到,bit数组的长度取决于最大的那个数值10。

    如果我们用byte数组来存储,那么需要byte数组的长度为 10/8 + 1;

    下面的代码表示一个简单的BitMap的数据结构:

    class BitMap {
        private byte[] bits;
        private int maxValue;
        private int capacity;
    
        public BitMap(int maxValue) {
            this.maxValue = maxValue;
            capacity = (maxValue >> 3) + 1;
            bits = new byte[capacity];
        }
    }
    

    添加数据

    添加数据,需要快速地定位到这个元素要存到byte数组中的哪个位置,这里的位置有两个概念:

    • index : 数据保存在byte数组的哪个索引下;
    • position : 数据在对应的byte中的位置;

    以10为例:

    index = 10 / 8;
    position = 10 % 8;
    

    定位到10需要保存的位置后,怎么把对应位置的bit改为1呢?这里可以用“位或”运算。将10添加到BitMap中的完整步骤如下:

    • 计算index = 10 / 8 = 1;
    • 计算position = 10 % 8 = 2;
    • 将byte[1] 中的数据与 00000100 做“位或”运算(00000100是对1左移2得到的),目的是将对应的bit改为1

    完整的代码如下:

        public void add(int num) {
            int index = num / 8;
            int position = num % 8;
            bits[index] |= (1 << position);
        }
    

    判断数字是否存在

    直接使用“位与”运算即可,代码如下:

        public boolean contains(int num) {
            int index = num / 8;
            int position = num % 8;
            return (bits[index] & (1 << position)) != 0;
        }
    

    main 方法如下

    public class Demo {
        public static void main(String[] args) {
            BitMap bm = new BitMap(100);
            bm.add(1);
            bm.add(13);
            bm.add(57);
            bm.add(100);
    
            System.out.println("3:" + (bm.contains(3) ? "存在" : "不存在"));
            System.out.println("13:" + (bm.contains(13) ? "存在" : "不存在"));
        }
    }
    

    运行结果:

    3:不存在
    13:存在
    
  • 相关阅读:
    MongoDB 创建账户
    MongoDB高可用集群配置方案
    学习CEGUI亟待解决问题一:文本控件的格式问题
    第一讲
    ERP初阶(三):MRP基本原理
    ERP初阶(四):MRP基本构成
    学习CEGUI亟待解决问题二:消息事件传递机制问题
    Groovy处理null对象为空字符串
    silverlight与CSLA的快速应用05安装CslaExtension
    silverlight与CSLA的快速应用08客户端的CSLA代码
  • 原文地址:https://www.cnblogs.com/lwmp/p/13628426.html
Copyright © 2011-2022 走看看