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

深入学习数据结构之bitmap(四)的更多相关文章

  1. Redis学习——数据结构介绍(四)

    一.简介 作为一款key-value 的NoSQL数据库,Redis支持的数据结构比较丰富,有:String(字符串) .List(列表) .Set(集合) .Hash(哈希) .Zset(有序集合) ...

  2. 20172328《程序设计与数据结构》实验四 Android程序设计报告

    20172328<程序设计与数据结构>实验四 Android程序设计报告 课程:<程序设计与数据结构> 班级: 1723 姓名: 李馨雨 学号:20172328 实验教师:王志 ...

  3. 一种很有意思的数据结构:Bitmap

    昨晚遇到了一种很有意思的数据结构,Bitmap. Bitmap,准确来说是基于位的映射.其中每个元素均为布尔型(0 or 1),初始均为 false(0).位图可以动态地表示由一组无符号整数构成的集合 ...

  4. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第四章:Direct 3D初始化

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第四章:Direct 3D初始化 学习目标 对Direct 3D编程在 ...

  5. 从一道高大上的面试题来学习位图算法BitMap

    今天我偶然刷到了一篇文章,"华为二面:一个文件里面有5亿个数据,一行一个,没有重复的,进行排序".不知道又是哪个无良媒体瞎起的标题,夺人眼球. 不过说归说,这题听着就很高大上,5亿 ...

  6. 我的MYSQL学习心得(十四) 备份和恢复

    我的MYSQL学习心得(十四) 备份和恢复 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) ...

  7. SqList *L 和 SqList * &L的区别/学习数据结构突然发现不太懂 小祥我查找总结了一下

    小祥在学习李春葆的数据结构教程时发现一个小问题,建立顺序表和输出线性表,这两个函数的形参是不一样的. 代码在这里↓↓↓ //定义顺序表L的结构体 typedef struct { Elemtype d ...

  8. 【Unity Shaders】学习笔记——SurfaceShader(四)用纹理改善漫反射

    [Unity Shaders]学习笔记——SurfaceShader(四)用纹理改善漫反射 转载请注明出处:http://www.cnblogs.com/-867259206/p/5603368.ht ...

  9. OpenGL学习之路(四)

    1 引子 上次读书笔记主要是学习了应用三维坐标变换矩阵对二维的图形进行变换,并附带介绍了GLSL语言的编译.链接相关的知识,之后介绍了GLSL中变量的修饰符,着重介绍了uniform修饰符,来向着色器 ...

随机推荐

  1. Tcl学习之--列表|字典

    [列表|字典] Tcl使用列表来处理各种集合,比方一个目录中的全部文件,以及一个组件的全部选项.最简单的列表就是包括由随意个空格.制表符.换行符.分隔的随意多个元素的字符串.比方: JerryAlic ...

  2. IOS开发基础之—MD5加密算法【转】

    原文地址:http://blog.csdn.net/pjk1129/article/details/6855024 #import <CommonCrypto/CommonDigest.h> ...

  3. 使用 C# 开发智能手机软件:推箱子(三)

    这是"使用 C# 开发智能手机软件:推箱子"系列文章的第三篇.在这篇文章中,介绍 Common/Block.cs 源程序文件.   1 namespace Skyiv.Ben.Pu ...

  4. java定时器2-spring实现

    spring定时器(基于xml) spring定时器(基于注解) quartz定时器 1.使用基于xml配置的spring定时器 首先编写定时任务类Mytask public class Mytask ...

  5. 记一次部署java项目的问题

    项目里面有自动化任务, tomcat 错误信息 Table 'xxx.QRTZ_TRIGGERS' doesn't exist 提示在mysql中找不到这个表. 但mysql中确实存在,但名字是:qr ...

  6. [原创] [C#] 转换Excel数字列号为字母列号

    转换Excel数字列号为字母列号 例如: 0 -> A 26 -> AA private static string GetColumnChar(int col) { ; ; ) ) + ...

  7. Android 6.0 RK3288 ROM编译详解+命令详解【转】

    本文转载自:http://blog.csdn.net/MLQ8087/article/details/58607692 Android 6.0 RK3288 ROM编译详解+命令详解 原创 2017年 ...

  8. openssl动态库编译

    通常Linux系统自带OpenSSL,但是其so文件由于没有debug信息,因此无法跟踪内部函数,对于学习 不太方便,需要通过源码重新安装.         我的Linux系统是CentOS7,自带的 ...

  9. BZOJ_5343_[Ctsc2018]混合果汁_二分答案+主席树

    BZOJ_5343_[Ctsc2018]混合果汁_二分答案+主席树 题意:给出每个果汁的价格p,美味度d,最多能放的体积l.定义果汁混合后的美味度为果汁的美味度的最小值. m次询问,要求花费不大于g, ...

  10. [转]json.dumps和json.loads区别

    原文json.dumps loads 终于区分出来了 原来每次遇到json loads/dumps始终搞不清方向,写段代码试下: [python] view plain copy print? imp ...