位图BitMap的原理和应用场景

题目

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

分析

由于一个Int整数为4个字节(Byte),那所需要的内存空间为 20亿 * 4字节 ≈ 7.45 GB。由于电脑内存只有2GB,无法一次性加载整个数据集到内存中进行查找,所以我们得换个思路。

已知一个字节由八个二进制位组成(如:10101001),因此我们可以用一个二进制位(Bit)标记一个整数是否存在,存在标记为1,不存在标记为0,具体如下:

Number 0 1 2 3 4 5 6 7
Bit 1 0 0 1 0 1 0 1

表格标记了0到7的数字,其中 0、3、5和7被标记为1,即集合中存在0、3、5和7,可表示为:int[ ] a = { 0, 3, 5, 7 },这种 位映射 的方式被称为 bit-map(位图) 。 因为1Int = 4Bytet = 32Bit,所以一个Int所占的二进制位可以映射32个数字,相当于压缩了32倍,那么之前20亿个整数所需要的7.45GB内存可缩减至238.41MB,至此该数据集可以一次性加载到2G内存的电脑上。

详解

一个Int可以映射32个数,那我们最大可申请(n / 32) + 1个容量的数组,即:

int[] arr = new int[(n / 32) + 1];

其中:

arr[0]:可映射0~31的数
arr[1]:可映射32~63的数
arr[2]:可映射64~95的数
...

添加数字number到数组

  1. 首先计算数字number在arr数组中的下标index,解:
// 数字number除以int的位数32,得到arr数组中的下标index,使用位运算优化可得:
int index = number >> 5;
  1. 其次计算数字number在arr[index]中的二进制位position,解:
// 数字number模以int的位数32,得到元素的二进制位position,使用位运算优化可得:
int position = number & (32 - 1);
  1. 最后取出 之前存放的元素新的元素 进行| 或运算,相当于取两边二进制位的并集,然后再赋值给数组。
arr[index] = arr[index] | (1 << position);

最终的函数可为:

public void add(int number){ 
    int index = number >> 5;
    int position = number & 31;
    arr[index] |= 1 << position;
}

注: | 或运算相当于取并集,列:0101 | 0011 = 0111

从数组中移除数字number

标记一个数是否存在,是将其二进制位设为1,如果要移除就把该位置设为0,相当于位运算中的 ~ 取反。最后在和 之前存放的元素 进行 & 与运算,相当于取两边二进制位的交集,然后再赋值给数组。

arr[index] = arr[index] & ~(1 << position);

最终的函数可为:

public void remove(int number){ 
    int index = number >> 5;
    int position = number & 31;
    arr[index] &= ~(1 << position);
}

注: & 与运算相当于取交集,列:0101 & 0011 = 0001

判断数字number是否存在

确认该数字的位置,把这个数无符号右移到最低位,然后在和1进行 & 与运算,去除高位的数,最后判断这个数是1还是0,即存在还是不存在。

public boolean contains(int number) {
    int index = number >> 5;
    int position = number & 31;
    return ((arr[index] >>> position) & 1) == 1;
}

应用

位图算法应用场景,例如:

  1. 布尔型集合操作:位图还可以进行位运算,如 & 与(AND)、| 或(OR)、^ 异或(XOR)、~ 取反(NOT)等操作,以支持高效的集合运算,比如并集、交集、差集等。
  2. 数据压缩:位图算法可以用于数据的压缩和压缩索引,例如在索引大量文本数据时,可以将每个单词使用位图表示,从而减少索引的存储空间。
  3. 布隆过滤器(Bloom Filter):布隆过滤器是一种概率型数据结构,利用位图算法和多个哈希函数,可以高效地判断一个元素是否属于一个集合。
  4. 数据去重:通过位图算法可以快速地判断一个元素是否已经存在于一个数据集合中,从而实现数据去重的功能。

场景

1.判断用户是否登录

思路: 使用redis的bitmap结构存储,只需要一个key,然后用户id为偏移量offset,如果在线就设置为1,不在线就设置为0。

2.统计用户打卡情况

思路: 使用时间作为缓存的key,然后用户id为偏移量offset,如果当日打过卡就设置为1。之后通过bitOp进行二进制计算算出在某段时间内用户的活跃情况。

3.视频属性的扩展

思路: 一个拥有亿级数据量的短视频app,视频存在各种属性(是否加锁、是否特效等等),需要做各种标记。key由属性的type组成。然后视频id为偏移量offset。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容