1. 什么是BitMap?
BitMap,可以想当然的从名字出发:点映射。它是以一个二进制点位表示数据的一种数据结构。那么具体是什么意思呢?
比如,在java中要存储0-20亿这个范围内的整数,一般做法是存int,但是这样一来它需要的空间是:8bit*4*2*10^9≈7.45G !而BitMap会怎么做呢?如下图所示,二进制位是1表示存在,为0表示不存在。
7 6 5 4 3 2 1 0 (整数)
int[0] 1 0 1 1 0 1 1 1 (BitMap二进制表示)
15 14 13 12 11 10 9 8 (整数)
int[1] 1 1 0 1 1 0 1 1 (BitMap二进制表示)
......
BitMap通过这种映射的方式,大大缩减了所需的空间,仅需 2*10^9/8/(1024*1024*1024)≈0.23G !
2. 如何存入/修改数据?
比如,在上面的例子中,要把6存进去,如何操作呢?
7 6 5 4 3 2 1 0 (整数)
int[0] 1 0 1 1 0 1 1 1 (存入前)
0 0 0 0 0 0 0 1 (整数1的二进制表示)
0 1 0 0 0 0 0 0 (1<<6)
int[0] 1 1 1 1 0 1 1 1 ( (1<<6) | int[0] )
存入时,除目标位为1外,其他位都为0,使用或(|)操作,使得之前除目标位为0的位继续为0,目标位变为1,其他之前是1的位仍然为1。
如果要去除5呢,又该如何操作?
7 6 5 4 3 2 1 0 (整数)
int[0] 1 0 1 1 0 1 1 1 (存入前)
0 0 0 0 0 0 0 1 (整数1的二进制表示)
0 0 1 0 0 0 0 0 (1<<5)
1 1 0 1 1 1 1 1 ( ~(1<<5) )
int[0] 1 0 0 1 0 1 1 1 ( ~(1<<5) & int[0] )
移除数据时,除目标位位0外,其他位都为1,使用与(&)操作,除目标位外,之前为1的位继续为1,之前为0的位仍然为0。
3. 思考
在看懂上面的操作后,对位操作符(与(&)、或(|)、异或(^))又有了新的认识,最直接的概括就是:或操作的目的是向原数据插入位(即将目标位变为1),与操作的目的是移除位(即将目标位变为0),而异或的操作可以认为是不进位的累加:
0 0 1 1 (A)
0 1 0 1 (B)
0 1 1 0 (A^B)