Bitmap,什么是Bitmap
a) Bitmap如何做到多维交叉计算的?
Bit即比特,是目前计算机系统里边数据的最小单位,8个bit即为一个Byte。一个bit的值,或者是0,或者是1;也就是说一个bit能存储的最多信息是2。
Bitmap可以理解为通过一个bit数组来存储特定数据的一种数据结构;由于bit是数据的最小单位,所以这种数据结构往往是非常节省存储空间。比如一个公司有8个员工,现在需要记录公司的考勤记录,传统的方案是记录下每天正常考勤的员工的ID列表,比如2012-01-01:[1,2,3,4,5,6,7,8]。假如员工ID采用byte数据类型,则保存每天的考勤记录需要N个byte,其中N是当天考勤的总人数。另一种方案则是构造一个8bit(01110011)的数组,将这8个员工跟员工号分别映射到这8个位置,如果当天正常考勤了,则将对应的这个位置置为1,否则置为0;这样可以每天采用恒定的1个byte即可保存当天的考勤记录。
综上所述,Bitmap节省大量的存储空间,因此可以被一次性加载到内存中。再看其结构的另一个更重要的特点,它也显现出巨大威力:就是很方便通过位的运算(AND/OR/XOR/NOT),高效的对多个Bitmap数据进行处理,这点很重要,它直接的支持了多维交叉计算能力。比如上边的考勤的例子里,如果想知道哪个员工最近两天都没来,只要将昨天的Bitmap和今天的Bitmap做一个按位的“OR”计算,然后检查那些位置是0,就可以得到最近两天都没来的员工的数据了,
机器1718
2022-07-28 · TA获得超过1853个赞
关注
比较经典的问题是: 在只能够使用2G的内存中,如何完成以下操作:
①:对10亿个不重复的整数进行排序。
②:找出10亿个数字中重复的数字。
无论是排序还是找重复的数字都需要将这10亿个数字加入到内存中在去进行操作,很明显,题目给出的2G内存限制说明了在这样的场景下是不能够将所有数都加入到内存中的
1000000000* 4/(1024* 1024* 1024) = 3.725G
那么这时候就需要用到 BitMap结构了
bitMap使用一个bit为0/1作为map的value来标记一个数字是否存在,而map的key值正是这个数字本身。
相比于一般的数据结构需要用4个byte去存储数值本身,相当于是节省了 4*8:1 = 32倍的内存空间
bitMap不一定要用bit数组,可以使用 int,long等等的基本数据类型实现,因为其实质都是在bit位上存数据,用哪种类型只是决定了最终实现出来的BitMap的内置数组中单个元素存放数据的多少
????例如:java中的BitSet使用Long数组
BitMap的实现当然少不了位运算,先来明确几个常见位运算,这是实现BitMap的基础:
set(bitIndex): 添加操作
????1 .确定该数处于数组中的哪个元素的位上
???? int wordIndex = bitIndex >> 5;
因为我用的是int[]实现,所以这里右移 5 位(2^5 = 32)
????2 .确定相对于该元素中的位置偏移
???? int bitPosition = bitIndex & ((1 << 5) - 1);
这里相当于是 bitIndex % (1<<5)的取模运算,因为当取模运算的除数是2的次幂,所以可以使用以下的位运算来计算,提升效率(对比HashMap的容量为什么总是2的幂次方的问题,HashMap求下标时也是使用 hash&(n-1))
tips: 位运算的优先级是低于+,-等等的,所以要加上括号,防止发生不可描述的错误
????3 .将该位置1
???? bits[wordIndex] |= 1 << bitPosition;
相当于是将指定位置处的bit值置1,其他位置保持不变,也就是将以这个bitIndex为key的位置为1
tips: 这里是参考了网上的各位大佬的文章,取余 + 按位或,又对比了下BitSet的源码:
???? words[wordIndex] |= (1L << bitIndex);
没有取余操作,直接|,这两个一样吗?答案当然是一样的
举个栗子:
???? 1 << 148 == 1<< 20 ????
???? 1L << 125 ==1L<< 61
即对于int和long型数据,直接左移其位数相当于是附带了对其的取模操作
总结 :使用Bit-map的思想,我们可以将存储空间进行压缩,而且可以对数字进行快速排序、去重和查询的操作。
Bloom Fliter是Bit-map思想的一种扩展,它可以在允许低错误率的场景下,大大地进行空间压缩,是一种拿错误率换取空间的数据结构
当一个元素加入布隆过滤器中的时候,会进行哪些操作:
当我们需要判断一个元素是否存在于布隆过滤器的时候,会进行哪些操作:
然后,一定会出现这样一种情况: 不同的字符串可能哈希出来的位置相同 (可以适当增加位数组大小或者调整我们的哈希函数来降低概率),因此: 布隆过滤器可能会存在误判的情况
总结来说就是: 布隆过滤器说某个元素存在,小概率会误判。布隆过滤器说某个元素不在,那么这个元素一定不在 。
Bloom Filter的应用: 常用于解决缓存穿透等场景。
相关文章
发表评论
评论列表
- 这篇文章还没有收到评论,赶紧来抢沙发吧~