BitMap的原理以及运用
位图(Bitmap),即位(Bit)的集合,是一种数据结构,可用于记录大量的0-1状态,在很多地方都会用到,比如Linux内核(如inode,磁盘块)、Bloom Filter算法等,其优势是可以在一个非常高的空间利用率下保存大量0-1状态。
BitMap的原理
BitMap 的基本原理就是用一个bit 位来存放某种状态,适用于大规模数据,但数据状态又不是很多的情况。通常是用来判断某个数据存不存在的。
举例:在Java里面一个int类型占4个字节,假如要对于10亿个int数据进行处理呢?10亿*4/1024/1024/1024=4个G左右,需要4个G的内存。
如果能够采用bit储,10_0000_0000Bit=1_2500_0000byte=122070KB=119MB, 那么在存储空间方面可以大大节省。
在Java里面,BitMap已经有对应实现的数据结构类java.util.BitSet,BitSet的底层使用的是long类型的数组来存储元素。
我们来看看具体存储:
对于1,3,5,7这四个数,如果存在的话,则可以这样表示:
1代表这个数存在,0代表不存在。例如表中01010101代表1,3,5,7存在,0,2,4,6不存在。那如果8,10,14也存在怎么存呢?如图,8,10,14我们可以存在第二个字节里
以此类推。
Map映射表
假设需要排序或者查找的总数N=10000000,那么我们需要申请内存空间的大小为int a[1 + N/32],其中:a[0]在内存中占32为可以对应十进制数0-31,依次类推:
bitmap表为:
a[0]--------->0-31
a[1]--------->32-63
a[2]--------->64-95
a[3]--------->96-127
..........
BitMap算法处理大数据问题的场景:
(1)给定10亿个不重复的正int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那10亿个数当中。
解法:遍历40个亿数字,映射到BitMap中,然后对于给出的数,直接判断指定的位上存在不存在即可。
(2)使用位图法判断正整形数组是否存在重复
解法:遍历一遍,存在之后设置成1,每次放之前先判断是否存在,如果存在,就代表该元素重复。
(3)使用位图法进行元素不重复的正整形数组排序
解法:遍历一遍,设置状态1,然后再次遍历,对状态等于1的进行输出,参考计数排序的原理。
(4)在2.5亿个整数中找出不重复的正整数,注,内存不足以容纳这2.5亿个整数
解法1:采用2-Bitmap(每个数分配2bit,00表示不存在,01表示出现一次,10表示多次,11无意义)。
解法2:采用两个BitMap,即第一个Bitmap存储的是整数是否出现,接着,在之后的遍历先判断第一个BitMap里面是否出现过,如果出现就设置第二个BitMap对应的位置也为1,最后遍历BitMap,仅仅在一个BitMap中出现过的元素,就是不重复的整数。
解法3:分治+Hash取模,拆分成多个小文件,然后一个个文件读取,直到内存装的下,然后采用Hash+Count的方式判断即可。
该类问题的变形问题,如已知某个文件内包含一些电话号码,每个号码为8位数字,统计不同号码的个数。8位最多99 999 999,大概需要99m个bit,大概10几m字节的内存即可。 (可以理解为从0-99 999 999的数字,每个数字对应一个Bit位,所以只需要99M个Bit==12MBytes,这样,就用了小小的12M左右的内存表示了所有的8位数的电话)
BitMap的一些缺点:
(1)数据碰撞。比如将字符串映射到 BitMap 的时候会有碰撞的问题,那就可以考虑用 Bloom Filter 来解决,Bloom Filter 使用多个 Hash 函数来减少冲突的概率。
(2)数据稀疏。又比如要存入(10,8887983,93452134)这三个数据,我们需要建立一个 99999999 长度的 BitMap ,但是实际上只存了3个数据,这时候就有很大的空间浪费,碰到这种问题的话,可以通过引入 Roaring BitMap 来解决。
例子:
从正整数数组中寻找重复的整数
import java.util.BitSet;
import java.util.HashSet;
import java.util.Set; public class TestBitMap {
//假设数据是以数组的形式给我们的
public static Set test(int[] arr) {
int j = 0;
//避免返回重复的数,存在Set里
Set output = new HashSet();
BitSet bitSet = new BitSet(Integer.MAX_VALUE);
int i = 0;
while (i < arr.length) {
int value = arr[i];
//判断该数是否存在bitSet里
if (bitSet.get(value)) {
output.add(value);
} else {
bitSet.set(value, true);
}
i++;
}
return output;
}
//测试
public static void main(String[] args) {
int[] t = {1,2,3,4,5,6,7,8,3,4,9};
Set t2 = test(t);
System.out.println(t2);
}
}
总结
本文主要介绍了BitMap算法的基本原理和应用案例,其本质上是采用了bit位来表示元素状态,从而在特定场景下能够极大的节省存储空间,非常适合对海量数据的查找,判重,删除等问题的处理。
其他参考:
https://www.cnblogs.com/hongdada/p/8267032.html
https://www.cnblogs.com/gczr/p/7358813.html
BitMap的原理以及运用的更多相关文章
- BitMap的原理和实现
相关概念 基础类型 在java中: byte -> 8 bits -->1字节 char -> 16 bit -->2字节 short -> 16 bits --> ...
- bitmap位图原理和实现
引子 首先通过一道题来理解什么是bitmap. 题目:我有40亿个整数,再给一个新的整数,我需要判断新的整数是否在40亿个整数中,你会怎么做? 分析: 假设一个int占4个字节(32位),40个亿个整 ...
- Android性能优化:谈话Bitmap内存管理和优化
最近除了那些忙着项目开发的事情,目前正在准备我的论文.短的时间没有写博客,今晚难得想总结.只要有一点时间.因此,为了凑合用,行.唠叨罗嗦,直接进入正题. 从事Android自移动终端的发展,想必是常常 ...
- Android性能优化之Bitmap的内存优化
1.BitmapFactory解析Bitmap的原理 BitmapFactory提供的解析Bitmap的静态工厂方法有以下五种: Bitmap decodeFile(...) Bitmap decod ...
- Android性能优化系列之Bitmap图片优化
https://blog.csdn.net/u012124438/article/details/66087785 在Android开发过程中,Bitmap往往会给开发者带来一些困扰,因为对Bitma ...
- 大数据分析常用去重算法分析『Bitmap 篇』
大数据分析常用去重算法分析『Bitmap 篇』 mp.weixin.qq.com 去重分析在企业日常分析中的使用频率非常高,如何在大数据场景下快速地进行去重分析一直是一大难点.在近期的 Apache ...
- BitMap算法知识笔记以及在大数据方向的使用
概述 所谓的BitMap算法就是位图算法,简单说就是用一个bit位来标记某个元素所对应的value,而key即是该元素,由于BitMap使用了bit位来存储数据,因此可以大大节省存储空间,这是很常用的 ...
- Redis系列8:Bitmap实现亿万级数据计算
Redis系列1:深刻理解高性能Redis的本质 Redis系列2:数据持久化提高可用性 Redis系列3:高可用之主从架构 Redis系列4:高可用之Sentinel(哨兵模式) Redis系列5: ...
- 深入浅出RxJava
深入浅出RxJava(一:基础篇) 深入浅出RxJava(二:操作符) 深入浅出RxJava三--响应式的好处 深入浅出RxJava四-在Android中使用响应式编程 RxJava 到底是什么? 一 ...
随机推荐
- Spring Boot2.0之纯手写框架
框架部分重点在于实现原理,懂原理! 废话不多说,动手干起来! SpringMVC程序入口? 没有配置文件,Spring 容器是如何加载? 回顾我们之前搭建Spring Boot项目使用的pom 引入的 ...
- nginx应用 突破高并发的性能优化
摘自:http://www.cnblogs.com/kevingrace/p/6094007.html 在日常的运维工作中,经常会用到nginx服务,也时常会碰到nginx因高并发导致的性能瓶颈问题. ...
- html5--1.14 特殊符号的使用
html5--1.14 特殊符号的使用 学习要点: 实体的概念一个表格小实例 1.HTML 实体 在 HTML 中,某些字符是预留的. 在 HTML 中不能使用小于号(<)和大于号(&am ...
- kvm初体验之三:vm的安装及管理
Host: CentOS release 6.4 (Final) Guest: CentOS release 6.6 (Final) 全程以root身份操作 1. host上创建桥br0 参考< ...
- &&、||和&、|的区别
1. && .|| 和 &.| 都是逻辑运算符,前两个 与后两个的区别就在于 &&.|| 有"短路"现象,而& .| 则没有. 例如 ...
- 程序猿老公去米国参加 WWDC,顺便想带渡老婆蜜月,如何办签证?
这个问题要拆开描述比较好:1. 老公是苹果开发者,抽中了2014 WWDC购票机会,打算自费去参加.如果自己成行,应该办何种签证?2. 顺带,两人新婚半年还未安排蜜月,打算提前几天过去先游览一下西海岸 ...
- JavaMail API的应用
JavaMail API 是一个用于阅读.编写和发送电子消息的可选包(标准扩展),用来创建邮件用户代理(Mail User Agent,MUA)类型程序. JavaMail API 需要 JavaBe ...
- linux命令学习笔记-md5sum 命令详解
前言 在网络传输.设备之间转存.复制大文件等时,可能会出现传输前后数据不一致的情况.这种情况在网络这种相对更 不稳定的环境中,容易出现.那么校验文件的完整性,也是势在必行的. 使用说明 md5sum命 ...
- 「LuoguP3389」【模板】高斯消元法
题目背景 Gauss消元 题目描述 给定一个线性方程组,对其求解 输入输出格式 输入格式: 第一行,一个正整数 nn 第二至 n+1n+1行,每行 n+1n+1 个整数,为a_1, a_2 \cdot ...
- 【Python】数组排序
1.numpy库:argsort() argsort函数返回的是数组值从小到大的索引值(升序排列) 一维: In [1]: import numpy as np In [2]: x = np.arra ...