位图(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的原理以及运用的更多相关文章

  1. BitMap的原理和实现

    相关概念 基础类型 在java中: byte -> 8 bits -->1字节 char -> 16 bit -->2字节 short -> 16 bits --> ...

  2. bitmap位图原理和实现

    引子 首先通过一道题来理解什么是bitmap. 题目:我有40亿个整数,再给一个新的整数,我需要判断新的整数是否在40亿个整数中,你会怎么做? 分析: 假设一个int占4个字节(32位),40个亿个整 ...

  3. Android性能优化:谈话Bitmap内存管理和优化

    最近除了那些忙着项目开发的事情,目前正在准备我的论文.短的时间没有写博客,今晚难得想总结.只要有一点时间.因此,为了凑合用,行.唠叨罗嗦,直接进入正题. 从事Android自移动终端的发展,想必是常常 ...

  4. Android性能优化之Bitmap的内存优化

    1.BitmapFactory解析Bitmap的原理 BitmapFactory提供的解析Bitmap的静态工厂方法有以下五种: Bitmap decodeFile(...) Bitmap decod ...

  5. Android性能优化系列之Bitmap图片优化

    https://blog.csdn.net/u012124438/article/details/66087785 在Android开发过程中,Bitmap往往会给开发者带来一些困扰,因为对Bitma ...

  6. 大数据分析常用去重算法分析『Bitmap 篇』

    大数据分析常用去重算法分析『Bitmap 篇』  mp.weixin.qq.com 去重分析在企业日常分析中的使用频率非常高,如何在大数据场景下快速地进行去重分析一直是一大难点.在近期的 Apache ...

  7. BitMap算法知识笔记以及在大数据方向的使用

    概述 所谓的BitMap算法就是位图算法,简单说就是用一个bit位来标记某个元素所对应的value,而key即是该元素,由于BitMap使用了bit位来存储数据,因此可以大大节省存储空间,这是很常用的 ...

  8. Redis系列8:Bitmap实现亿万级数据计算

    Redis系列1:深刻理解高性能Redis的本质 Redis系列2:数据持久化提高可用性 Redis系列3:高可用之主从架构 Redis系列4:高可用之Sentinel(哨兵模式) Redis系列5: ...

  9. 深入浅出RxJava

    深入浅出RxJava(一:基础篇) 深入浅出RxJava(二:操作符) 深入浅出RxJava三--响应式的好处 深入浅出RxJava四-在Android中使用响应式编程 RxJava 到底是什么? 一 ...

随机推荐

  1. hadoop —— MapReduce例子 (数据排序)

    参考:http://eric-gcm.iteye.com/blog/1807468 file1.txt: 2 32 654 32 15 756 65223 file2.txt: 5956 22 650 ...

  2. 吴恩达机器学习笔记(十二) —— Application Example: Photo OCR(完)

    主要内容: 一.Photo OCR 二.Getting lots of data:artificial data synthesis 三.Ceiling analysis 一.Photo OCR Ph ...

  3. Spring 4.3 的新功能和增强

    转载自https://my.oschina.net/waylau/blog/698186 核心容器改进 核心容器额外提供了更丰富的元数据来改进编程. 默认 Java 8 的方法检测为 bean 属性的 ...

  4. Java_Time_01_获取当前时间

    1. Date SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// ...

  5. 详解 pthread_detach()函数

    pthread_t 类型定义: typedef unsigned long int pthread_t; //come from /usr/include/bits/pthread.h 用途:pthr ...

  6. 1091 Acute Stroke (30)(30 分)

    One important factor to identify acute stroke (急性脑卒中) is the volume of the stroke core. Given the re ...

  7. RMI RPC socket

      1.RPC RPC(Remote Procedure Call Protocol)远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议.RPC不依赖于具体的 ...

  8. jquery.one()

    one() 方法为被选元素附加一个或多个事件处理程序,并规定当事件发生时运行的函数. 当使用 one() 方法时,每个元素只能运行一次事件处理器函数. 也就是,绑定的function,只会执行一次. ...

  9. 【转】unittest执行测试用例的N种姿势总结

    原文地址:https://www.cnblogs.com/fighter007/p/9514453.html 1.我们写几个方法,用来做测试用例 2.我们在另一文件中引用这个模块下面的所有类方法,先看 ...

  10. python 进行web测试

    1:安装nosetests Python 单元测试框架之Nose http://blog.sina.com.cn/s/blog_65a8ab5d0101fihb.html Python nose te ...