Bitmap算法中文又叫做位图算法
-
BitMap的基本思想就是用一个bit位来标记某个元素对应的Value,而Key即是该元素。由于采用了Bit为单位来存储数据,因此可以大大节省存储空间
-
BitMap如看成一种数据结构,更易于理解
示例理解
3个数字,
3
5
6
需要存储,java中,需要耗费3个int类型,一个int类型4个字节,合计12个字节
换做位存储(位置从右向左)
1个字节8个位,在二进制中,1个位只能有0和1
3 存储时 00001000
5 存储时 00100000
6 存储时 01000000
3个二进制进行与操作,01101000即为3个数字的最终存储结果,只耗费了1个字节,并且才使用了1个字节3/8的空间
再比如 in_array 操作
假设有这样一个需求:在20亿个随机整数中找出某个数m是否存在其中,并假设32位操作系统,4G内存。
在Java中,
int占4字节,1字节=8位(1 byte = 8 bit)如果每个数字用int存储,那就是20亿个int,因而占用的空间为(2000000000*4/1024/1024/1024)≈7.45G
按位存储
20亿个数就是20亿位,占用空间约为(2000000000/8/1024/1024/1024)≈0.233G
优点和缺点
优点:由于采用了Bit为单位来存储数据并建立映射关系来查找位置,因此可以大大减少存储空间,加快在大量数据中查询的时间。(有点哈希表的意思,但哈希中的value值数据类型可以丰富多样,而BitMap最终查到的value只能表示简单的几种状态。)
缺点:BitMap中的查询结果(value)能表达的状态有限,且所有的数据不能重复。即不可对重复的数据进行排序和查找。
图示例
来自小灰
https://zhuanlan.zhihu.com/p/54783053
实践
demo1
获取两个类型在某个位置并集或者交集是否允许,可将表格数据通过位进行存储,例如
类型1 为 1101,二进制与十进制相互转化
通过位运算获取结果
demo2
一个公司有20个员工,现在需要记录公司的考勤记录
传统的方案是记录下每天正常考勤的员工的ID列表,比如
出勤日期 | 员工ID |
---|---|
2024-01-01 | 1 |
2024-01-01 | 2 |
2024-01-02 | 3 |
2024-01-02 | 5 |
2024-01-02 | 19 |
假如员工ID采用int16数据类型,则保存每天的考勤记录仅员工ID这一列需要N*8个byte,其中N是当天考勤的总人数 |
另一种方案则是构造3个8bit(即3byte),将这20个员工跟员工号分别映射到这20个位置,如果当天正常考勤了,则将对应的这个位置置为1,否则置为0;这样可以每天采用恒定的1条数据并且3个byte即可保存当天的考勤记录
出勤日期 | 该日出勤统计 |
---|---|
2024-01-01 | 00000000 00000000 00000011 |
2024-01-02 | 00000100 00000000 00010100 |
当然,你可以根据多种存储方案,例如在mysql中将这3个byte转化成10进制int类型存储、redis高版本的bitmap类型存储等。。