1.bitmap可以用来存储用户与标签的对应关系,方便存储与查询
2.查询操作
//查询使用苹果手机的程序员用户
//程序员用户
00000001
//使用苹果手机用户
00000011
&
//得到查询结果
00000001
//查询男性或00后用户
//男性用户
00000011
|
//00后用户
00000100
//得到结果
00000111
//查询不是90后的用户
//90后用户
00000110
^
//全量用户(包含00,90)
00001110
//得到不是90后用户
00001000
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
.......
如何判断int数字在tmp数组的哪个下标,这个其实可以通过直接除以32取整数部分,例如:整数8除以32取整等于0,那么8就在tmp[0]上。另外,我们如何知道了8在tmp[0]中的32个位中的哪个位,这种情况直接mod上32就ok,又如整数8,在tmp[0]中的第8 mod上32等于8,那么整数8就在tmp[0]中的第八个bit位(从右边数起)。
一个数怎么快速定位它的索引号,也就是说搞清楚byte[index]的index是多少,position是哪一位。举个例子吧,例如add(14)。14已经超出byte[0]的映射范围,在byte[1]范围之类。那么怎么快速定位它的索引呢。如果找到它的索引号,又怎么定位它的位置呢。Index(N)代表N的索引号,Position(N)代表N的所在的位置号。
Index(N) = N/8 = N >> 3;
Position(N) = N%8 = N & 0x07;
add操作
//得到第几行索引
let byteIndex = Math.floor(k / 16);
//得到第几列的索引
let bitIndex = k % 16;
//将1移动到索引的位置并修改该位置
this.blk[byteIndex] = this.blk[byteIndex] | (1 << bitIndex);
clear操作
let byteIndex = Math.floor(k / 16);
let bitIndex = k % 16;
this.blk[byteIndex] &= ~(1 << bitIndex)
contain操作
!((this.blk[byteIndex] & (1 << bitIndex)) === 0);
完整实现
class BitMap {
constructor(n) {
this.nbits = n;
this.blk = new Array(Math.floor(n / 16) + 1);
this.blk.fill(0);
}
get(k) {
if( k > this.nbits) return false;
let byteIndex = Math.floor(k / 16);
let bitIndex = k % 16;
return !((this.blk[byteIndex] & (1 << bitIndex)) === 0);
}
set(k) {
if( k > this.nbits) return;
let byteIndex = Math.floor(k / 16);
let bitIndex = k % 16;
this.blk[byteIndex] = this.blk[byteIndex] | (1 << bitIndex);
}
clear(k){
if( k > this.nbits) return;
let byteIndex = Math.floor(k / 16);
let bitIndex = k % 16;
return !((this.blk[byteIndex] &= (~(1 << bitIndex))) === 0)
}
}
let aBitMap = new BitMap(20);
aBitMap.set(1);
aBitMap.set(3);
aBitMap.set(5);
aBitMap.set(7);
aBitMap.set(9);
aBitMap.set(11);
aBitMap.set(13);
aBitMap.set(15);
aBitMap.set(17);
aBitMap.set(19);
console.log(aBitMap.clear(3))
console.log(aBitMap.get(3))
console.log(aBitMap.get(1))
console.log(aBitMap.get(5))
console.log(aBitMap.get(7))
console.log(aBitMap.get(9))
// console.log(aBitMap.get(3))
// for(let i = 0; i < 21; i++) {
// console.log(aBitMap.get(i));
// }