深入学习数据结构之bitmap(四)

Bitmap,今天我们来分析一下bitmap的实现原理以及它的使用场景。

一、使用场景:

  1、对于大量数据(几千个数据的就不要在废话了),且无重复或者可以忽略重复的数字。为啥这里要强调无重复,因为在bitmap实现过程中再试无法处理。

  2、用于查询新数字是存在在已知数据中。(如果用于全量打印之类的,循环性能上没有太大优势,内存空间上会有一定的优势)

  3、查询速度能控制在1级别(what?难道连一次循环都不需要吗?是的,都不需要循环,都不需要循环,都不需要循环,重要的事情强调三次。)

二、实现原理

  理论实现方案1:

    结构 List<Integer> datas;

    boolean contains(Integer i){ for循环获取}

    结论:Integer 由一个 Integer是一个Class对象,(使用Java的银都知道,炒鸡占用内存啊,过儿……)

    楼主:这得多少内存啊,容我仔细算算……

  理论实现方案2:

    结构 List<int> datas;

    boolean contains(int i){for 循环获取}

    结论:int 对 Integer 说:老弟,每个对象只需要4个字节即(32位)就够了,比你少了好多内存啊。

    楼主:那你contains还要for循环,你这是O1,O1,O1 没听懂啊。(过儿……)

  理论实现方案3:

    结构 int [] datas;

    boolean contains(int i){

      if(datas[i] == 1) {return true;}

      else{ return false;}

    }

    结论:利用下标的方式可以快速的获取数组中对应下标的值,如果为1 则表示存在,否则表示不存在。

    缺点:一开始就需要初始化一个超级无敌大的数组

    楼主:嗯,不错不错,给你点赞,查询不需要循环了。你比楼上的强多了。不过 一个int 4个字节 32位,如果最大值为 1000,000,000  那还是需要很多内存啊。

    4000,000,000字节 = 3814MB ,这个……

  理论实现方案4:

    结构 int[] datas;

    boolean contains(int i){ return "请参考具体实现……"}

    楼主:你这个不是和上面的涨的一样吗,难道你想抄袭吗^_^

    过儿:虽然长得像,可是内在不一样啊。请听我细细说来……

    结论:一个int 4个字节 32位,方案3中,每个int只保存一个int值,我这个一个int 利用每一位进行保存一个int值,一个int可以保存32个值,内存只用1/32。厉害吧……

      如果最大值为 1000,000,000   即 125,000,000字节 = 120MB

    优点:利用每一个位进行保存一个数字,内存消耗可以大幅度的降低。

    楼主:那你来实现一下。666~~~

三、Java 实现

public class BitMap {

    private int[] datas;
    private int m = 31; // 0-31 个位数

    BitMap(int max) {
        int count = (max >> 5) + 1;
        datas = new int[count];
        System.out.println("datas.length:"+datas.length);
    }
    // 添加
    void add(int i) {
        int c = i >> 5; // 计算在那个datas下标中
        int k = i & m; // 计算标记位k
        int d = datas[c];
        d = d | (1 << k); // 标记k位 值为 1
        datas[c] = d;
    }
    // 查询
    boolean contains(int i) {
        int c = i >> 5; // 计算在按个datas下标中
        int k = i & m; // 计算标记位k
        int d = datas[c];
        int n = d >> k & 1; // 获取第K位的标记值
        if (n == 1) {
            return true;
        } else {
            return false;
        }
    }

    public static void main(String[] args) {
        BitMap m = new BitMap(1000000000);

        m.add(39491);
        m.add(15157);
        m.add(26304);
        m.add(19857);
        m.add(17881);
        m.add(16593);
        m.add(478);
        m.add(8398);
        m.add(2011); //
        m.add(23134); //

        System.out.println("23134:"+m.contains(23134));
        System.out.println("2011:"+m.contains(2011));
        System.out.println("152:"+m.contains(152));

    }

}

运行结果:

datas.length:31250001
23134:true
2011:true
152:false

计算内存消耗:

     System.gc();
        long total = Runtime.getRuntime().totalMemory(); // byte
        long m1 = Runtime.getRuntime().freeMemory();
        System.out.println("before:" + (total - m1));
         
        BitMap m = new BitMap(1000000000);
        
        long total1 = Runtime.getRuntime().totalMemory();
        long m2 = Runtime.getRuntime().freeMemory();
        System.out.println("after:" + (total1 - m2));

        long u= (total1 - m2) - (total - m1); // byte
        
        System.out.println("used:"+u/1024/1024+"M");

before:1958784
after:126958808
used:119M

简单实现了一下BitMap , 本例只用于学习使用。根据上面的代码可以看出,保存最大值为 1,000,000,000 的值,只需要 31250001个int 即 119MB

猜你喜欢

转载自www.cnblogs.com/xiaolangabc/p/10821664.html