首先先了解下按位插入。
如果给出一块长度为10bit的空间,也就是Bitmap,想要依次插入4,2,1,3需要怎么做?
第一步,开辟一块10bit的数组空间,每一个bit位对应着0-9得整型数,Bitmap的所有位都是0
第二步,把整数4存入Bitmap,存入下标4的位置,
第二步,把整数2存入Bitmap,存入下标2的位置,
第二步,把整数1存入Bitmap,存入下标1的位置,
第二步,把整数3存入Bitmap,存入下标3的位置,
这时候问存储了哪些元素,很明显就是4,2,1,3,而且这个可以利用位运算很方便的运算,并且可以用来去重操作。
一开始小灰是遇到了这样一个工作需求。
他是要把用户的一些用户个人信息,存入数据库中,一开始存入的个人信息并不多,
但是后来越来越多都信息要存入其中,一张表显得格外都臃肿,需要扩充很多的列才可以使用。这样子无疑是不好都方式。
这时候,可以巧妙都利用Btimap,
方法就像是倒排索引,信息不一定以用户为中心,而是以用户个人信息标签为中心,让每个标签存储包含此标签的所有用户id
例如
Name sex age occupation phone
小小 男 90后 程序员 苹果
大大 男 90后 程序员 三星
小大 女 00后 学生 小米
ID NAME
1 小小
2 大大
3 小大
同时可以拆分
sex Bitmap
男 1,2
女 3
Age Bitmap
90后 1,2
00后 3
Occupation Bitmap
程序员 1,2
学生 3
phone Bitmap
苹果 1
三星 2
小米 3
这样一来,就一目了然了。
这里有人要问了,为什么不存成哈希表呢。
这是因为,使用哈希表的话,每一个用户ID都要存成int或者long型,少则占用了4个字节,多则8个字节,而一个用户在Bitmap只是1bit,内存是哈希都1/32,甚至更少。
不仅如此,Bitmap在做并集和交集运算更加的方便。
看看Btimap的相关代码吧。
private long[] word; private int size; public MyBitmap(int size){ this.size = size; this.words = new long[(getWordIndex(size-1)+1)]; } /** * 判断Bitmap某一位的状态 * @param bitIndex 位图得第bitIndex位 */ public boolean getBit(int bitIndex){ if(bitIndex < 0 || bitIndex >size-1){ throw new IndexOutOfBoundsException("超过Bitmap有效范围"); } int wordIndex = getWordIndex(bitIndex); return (words[wordIndex] & (1L<<bitIndex))!=0; } /** * 把Bitmap某一位设置为true * @param bitIndex 位图的第bitIndex位 */ public void setBit(int bitIndex){ if(bitIndex <0 || bitIndex > size-1){ throw new IndexOutOfBoundsException("超过Bitmap有效范围"); } int wordIndex = getWordIndex(bitIndex); words[wordIndex] |= (1L<<bitIndex); } /** * 定位Bitmap某一位对应都word * @param bitIndex位图都第bitIndex位 */ private int getWordIndex(int bitIndex){ //右移6位,相当于除以64 return bitIndex >> 6; } public static void main(String[] args){ MyBitmap bitMap = new MyBitmap(128); bitMap.setBit(126); bitMap.setBit(75); System.out.println(bitMap.getBit(126)); System.out.println(bitMap.getBit(78)); }
到了这里就是《漫画算法》算法运用之Bitmap巧用都内容了,有趣的话题,下回继续分解。