海量数据处理之BitMap

有这样一种场景:一台普通PC,2G内存,要求处理一个包含40亿个不重复并且没有排过序的无符号的int整数,给出一个整数,问如果快速地判断这个整数是否在文件40亿个数据当中?

问题思考:

40亿个int占(40亿*4)/1024/1024/1024 大概为14.9G左右,很明显内存只有2G,放不下,因此不可能将这40亿数据放到内存中计算。要快速的解决这个问题最好的方案就是将数据搁内存了,所以现在的问题就在如何在2G内存空间以内存储着40亿整数。一个int整数在java中是占4个字节的即要32bit位,如果能够用一个bit位来标识一个int整数那么存储空间将大大减少,算一下40亿个int需要的内存空间为40亿/8/1024/1024大概为476.83 mb,这样的话我们完全可以将这40亿个int数放到内存中进行处理。

具体思路(BitMap思想):

1个int占4字节即4*8=32位,那么我们只需要申请一个int数组长度为 int tmp[1+N/32]即可存储完这些数据,其中N代表要进行查找的总数,tmp中的每个元素在内存在占32位可以对应表示十进制数0~31,所以可得到BitMap表:

tmp[0]:可表示0~31

tmp[1]:可表示32~63

tmp[2]可表示64~95

.......

那么接下来就看看十进制数如何转换为对应的bit位:

假设这40亿int数据为:6,3,8,32,36,......,那么具体的BitMap表示为:

(1)如何判断int数字放在哪一个tmp数组中:将数字直接除以32取整数部分(x/32),例如:整数8除以32取整等于0,那么8就在tmp[0]上;

(2)如何确定数字放在32个位中的哪个位:将数字mod32(x%32)。上例中我们如何确定8在tmp[0]中的32个位中的哪个位,这种情况直接mod上32就ok,又如整数8,在tmp[0]中的第8 mod上32等于8,那么整数8就在tmp[0]中的第八个bit位(从右边数起)。

一、什么是BitMap

Bit-Map会用Bit来标记某个元素对应的value,如何标记的呢,见下例:   我们现在有(1,2,5,8,10)数组,常规来说是这样声明的:

int[] array = {1, 2, 5, 8, 10}

上面这样声明会占用4×5个字节,即20个字节,少量数据可能没有什么特别大的感觉,如果数组长度为10,000,000,这样的方式就会占用4G的内存。

如果用Bit-Map的话,可以这样来组织:

byte[] bytes = new bytes[2];

bytes[0] = 01100100; // 就直接写二进制了

bytes[1] = 10100000;

例如:用位向量来表示数据: 1 、 3 、 6 、 10 、 100

// 1 3 6 10 100 
        BitSet bitSet = new BitSet(100); 
        bitSet.set(1,true); 
        bitSet.set(3,true); 
        bitSet.set(6,true); 
        bitSet.set(100,true); 
       for(int i=0;i<bitSet.size();i++){ 
      boolean b = bitSet.get(i); 
      if(b){ 
            System.out.println(i); 
             } 
         } 
       }

二、Bit-Map建立

1、开辟定长数组

Bit-Map会声明一个定长的byte/int数组,之后将数组内元素的所有Bit位均置为0,如下图:

2、遍历数据,并插入Bit-Map

上例来说,就会遍历array{1, 2, 5, 8, 10},并将所有的元素均插入Bit-Map中。Bit-Map是Hash的极致,那么key即为array[i]/8,value即在byte中的位置array[i]%8。而实际中为了效率,hash函数可能会有些出入。如下:

遍历插入之后的数据应该是这样的:

三、Bit-Map的基本思想

我们先来看一个具体的例子,假设我们要对0-7内的5个元素(4,7,2,5,3)排序(这里假设这些元素没有重复)。那么我们就可以采用Bit-map的方法来达到排序的目的。要表示8个数,我们就只需要8个Bit(1Bytes),首先我们开辟1Byte的空间,将这些空间的所有Bit位都置为0,如下图:

然后遍历这5个元素,首先第一个元素是4,那么就把4对应的位置为1(可以这样操作 p+(i/8)|(0x01<<(i%8)) 当然了这里的操作涉及到Big-ending和Little-ending的情况,这里默认为Big-ending),因为是从零开始的,所以要把第五位置为一(如下图):

然后再处理第二个元素7,将第八位置为1,,接着再处理第三个元素,一直到最后处理完所有的元素,将相应的位置为1,这时候的内存的Bit位的状态如下:

然后我们现在遍历一遍Bit区域,将该位是一的位的编号输出(2,3,4,5,7),这样就达到了排序的目的。

优点:1.运算效率高,不许进行比较和移位;

2.占用内存少,比如N=10000000;只需占用内存为N/8=1250000Byte=1.25M

缺点:

所有的数据不能重复。即不可对重复的数据进行排序和查找。

算法思想比较简单,但关键是如何确定十进制的数映射到二进制bit位的map图。

四、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 
.......... 
那么十进制数如何转换为对应的bit位,下面介绍用位移将十进制数转换为对应的bit位。

位移转换

申请一个int一维数组,那么可以当作为列为32位的二维数组,

|                           32位                                       |

int a[0]    |0000000000000000000000000000000000000|

int a[1]    |0000000000000000000000000000000000000|

………………

int a[N]   |0000000000000000000000000000000000000|

例如十进制0,对应在a[0]所占的bit为中的第一位: 00000000000000000000000000000001

五、BitMap应用场景扩展

建立了Bit-Map之后,就可以方便的使用了。一般来说Bit-Map可作为数据的查找、去重、排序等操作。

如上面提及的10,000,000个数据存储问题,用Integer存储,耗费4G内存。改成Bit-Map,耗费125MB内存。但是实际中,可能由于数据中最大最小值相差太大,如{1,2 99999},只有三个数,但是最大最小相差悬殊,该方法就不适用了。

查找和去重都好理解,至于排序,有点类似桶排序,每个byte都是一个桶。

1、在3亿个整数中找出重复的整数个数,限制内存不足以容纳3亿个整数

对于这种场景可以采用2-BitMap来解决,即为每个整数分配2bit,用不同的0、1组合来标识特殊意思,如00表示此整数没有出现过,01表示出现一次,11表示出现过多次,就可以找出重复的整数了,其需要的内存空间是正常BitMap的2倍,为:3亿*2/8/1024/1024=71.5MB。

具体的过程如下:扫描着3亿个整数,组BitMap,先查看BitMap中的对应位置,如果00则变成01,是01则变成11,是11则保持不变,当将3亿个整数扫描完之后也就是说整个BitMap已经组装完毕。最后查看BitMap将对应位为11的整数输出即可。

2、对没有重复元素的整数进行排序

对于非重复的整数排序BitMap有着天然的优势,它只需要将给出的无重复整数扫描完毕,组装成为BitMap之后,那么直接遍历一遍Bit区域就可以达到排序效果了。

举个例子:对整数4、3、1、7、6进行排序:

直接按Bit位输出就可以得到排序结果了

3、已知某个文件内包含一些电话号码,每个号码为8位数字,统计不同号码的个数

8位最多99 999 999,大概需要99m个bit,大概10几m字节的内存即可。可以理解为从0-99 999 999的数字,每个数字对应一个Bit位,所以只需要99M个Bit==1.2MBytes,这样,就用了小小的1.2M左右的内存表示了所有的8位数的电话。

4、2.5亿个整数中找出不重复的整数的个数,内存空间不足以容纳这2.5亿个整数

将bit-map扩展一下,用2bit表示一个数即可:0表示未出现;1表示出现一次;2表示出现2次及以上,即重复,在遍历这些数的时候,如果对应位置的值是0,则将其置为1;如果是1,将其置为2;如果是2,则保持不变。或者我们不用2bit来进行表示,我们用两个bit-map即可模拟实现这个2bit-map,都是一样的道理。

关于BitMap的运用请参见:http://my.oschina.net/cloudcoder/blog/294810?fromerr=62qBkJF5

http://blog.csdn.net/hguisu/article/details/7880288

注:bitSet.size()返回此BitSet表示位值时实际使用空间的位数;一般为64的整数倍;

new BitSet(950)并不等于建立了一个950大小的BitSet,只是说构建出来的BitSet初始大小至少能容纳950个Bit,大小永远是系统控制的,而且它的大小是64的倍数,就算BitSet(1),它的大小也是64

BitSet能够保证"如果判定结果为false,那么数据一定是不存在的,但是如果结果为true,那么数据可能存在,也可能不存在(冲突覆盖)",即false==yes;true==maybe

时间: 2024-10-09 21:56:46

海量数据处理之BitMap的相关文章

海量数据处理算法—Bit-Map

原文:http://blog.csdn.net/hguisu/article/details/7880288 1. Bit Map算法简介 来自于<编程珠玑>.所谓的Bit-map就是用一个bit位来标记某个元素对应的Value, 而Key即是该元素.由于采用了Bit为单位来存储数据,因此在存储空间方面,可以大大节省. 2. Bit Map的基本思想 我们先来看一个具体的例子,假设我们要对0-7内的5个元素(4,7,2,5,3)排序(这里假设这些元素没有重复).那么我们就可以采用Bit-map

[算法系列之十八]海量数据处理之BitMap

一:简介 所谓的BitMap就是用一个bit位来标记某个元素对应的Value, 而Key即是该元素.由于采用了bit为单位来存储数据,因此在存储空间方面,可以大大节省. 二:基本思想 我们用一个具体的例子来讲解,假设我们要对0-7内的5个元素(4,7,2,5,3)排序(这里假设这些元素没有重复).那么我们就可以采用BitMap的方法来达到排序的目的.要表示8个数,我们就只需要8个bit(1Bytes). (1)首先我们开辟1字节(8bit)的空间,将这些空间的所有bit位都置为0,如下图: (2

海量数据处理--hash和bit-map

问题实例: 海量日志数据,提取出某日访问百度次数最多的那个IP. 答:对于ip,最多也就2^32个.所以可以很好地通过hash函数映射到内存中,再进行统计. IP最多为2^32个,为4G,一次放入内存中不行,可以采用分而治之的方法,先Hash(IP)/1024,将IP地址分别映射到1024个小文件中,每个文件4M,再将每个小文件中的IP放入内存中,进行hashmap,统计出出现频率最高的那个IP,最后可以得到1024个出现高频的IP,采用冒泡排序,可以迅速找出频率最高的那个IP.1 原理简述:

海量数据处理算法总结【超详解】

1. Bloom Filter [Bloom Filter]Bloom Filter(BF)是一种空间效率很高的随机数据结构,它利用位数组很简洁地表示一个集合,并能判断一个元素是否属于这个集合.它是一个判断元素是否存在集合的快速的概率算法.Bloom Filter有可能会出现错误判断,但不会漏掉判断.也就是Bloom Filter判断元素不再集合,那肯定不在.如果判断元素存在集合中,有一定的概率判断错误.因此,Bloom Filter不适合那些“零错误”的应用场合. 而在能容忍低错误率的应用场合

从hadoop框架与MapReduce模式中谈海量数据处理

前言 几周前,当我最初听到,以致后来初次接触Hadoop与MapReduce这两个东西,我便稍显兴奋,觉得它们很是神秘,而神秘的东西常能勾起我的兴趣,在看过介绍它们的文章或论文之后,觉得Hadoop是一项富有趣味和挑战性的技术,且它还牵扯到了一个我更加感兴趣的话题:海量数据处理. 由此,最近凡是空闲时,便在看“Hadoop”,“MapReduce”“海量数据处理”这方面的论文.但在看论文的过程中,总觉得那些论文都是浅尝辄止,常常看的很不过瘾,总是一个东西刚要讲到紧要处,它便结束了,让我好生“愤懑

从Hadoop框架与MapReduce模式中谈海量数据处理(含淘宝技术架构)

从hadoop框架与MapReduce模式中谈海量数据处理 前言 几周前,当我最初听到,以致后来初次接触Hadoop与MapReduce这两个东西,我便稍显兴奋,认为它们非常是神奇,而神奇的东西常能勾起我的兴趣,在看过介绍它们的文章或论文之后,认为Hadoop是一项富有趣味和挑战性的技术,且它还牵扯到了一个我更加感兴趣的话题:海量数据处理. 由此,近期凡是空暇时,便在看"Hadoop","MapReduce""海量数据处理"这方面的论文.但在看论

从Hadoop骨架MapReduce在海量数据处理模式(包括淘宝技术架构)

从hadoop框架与MapReduce模式中谈海量数据处理 前言 几周前,当我最初听到,以致后来初次接触Hadoop与MapReduce这两个东西,我便稍显兴奋,认为它们非常是神奇.而神奇的东西常能勾起我的兴趣.在看过介绍它们的文章或论文之后,认为Hadoop是一项富有趣味和挑战性的技术,且它还牵扯到了一个我更加感兴趣的话题:海量数据处理. 由此,近期凡是空暇时,便在看"Hadoop"."MapReduce""海量数据处理"这方面的论文.但在看论

海量数据处理方法

1.hashing 适用范围:快速查找,删除的基本数据结构,通常需要总数据量可以放入内存.  这里的hashing和 hashmap是不一样的概念,这里的hash指的是hashtable,可以看例子:(比较两个字符串的包含问题) 问题实例: 1).海量日志数据,提取出某日访问百度次数最多的那个IP. IP的数目还是有限的,最多2^32个,所以可以考虑使用hash将ip直接存入内存,然后进行统计. 2.bitmap 适用范围:可进行数据的快速查找,判重,删除,一般来说数据范围是int的10倍以下.

海量数据处理算法

1. Bloom Filter [Bloom Filter]Bloom Filter(BF)是一种空间效率很高的随机数据结构,它利用位数组很简洁地表示一个集合,并能判断一个元素是否属于这个集合.它是一个判断元素是否存在集合的快速的概率算法.Bloom Filter有可能会出现错误判断,但不会漏掉判断.也就是Bloom Filter判断元素不再集合,那肯定不在.如果判断元素存在集合中,有一定的概率判断错误.因此,Bloom Filter不适合那些"零错误"的应用场合. 而在能容忍低错误率