题目
关于用户标签的需求:用户标签包括用户的社会属性、生活习惯、消费行为等信息。例如,程序员,有驾照,单身等等。通过用户标签,可以对多样的用户群体进行统计。例如,统计用户的男女比例,统计喜欢旅游的用户数量等。
通常的思路,是使用关系型数据库,比如Occupation表示用户职位,gender表示性别等等。表的一行记录,为一个用户的标签。但是如果有很多标签的话,则需要给表加很多列,不好维护。
思路
Bitmap算法,在中文里又叫作位图算法
。位图,是指内存中连续的二进制位(bit),所组成的数据结构,该算法主要用于大量整数做去重和查询操作。
举例,有100bit的Bitmap,每一个bit位都表示着,从0到99的整型数。如果想用bit位,表示某些数字,只需将对应位的bit设置位1即可。例如,向100bit的Bitmap中,保存55,77,88,只需要将对应位设置为1即可。
这样,就可以用Bitmap和用户表里的id建立映射关系,假如一个程序员标签,有一个用户的id位99,只需要将表示程序员标签的Bitmap的第99位,设置为1,就表示id为99的用户职位是程序员。
还可以,进行与,或,异或等逻辑运算。
假设,有两个10bit的Bitmap,一个表示是男性的标签{0,0,0,0,0,0,1,1,1,0},一个表示是00后的标签{0,0,0,0,0,0,0,0,1,0},求这10bit的Bitmap中,即是男性,也是00后的用户,进行逻辑&运算即可,或就进行|元素。非00后,就需要代表00后的标签和,全部的用户的Bitmap,进行异或运算,就是说,在全部用户的Bitmap中过滤掉是00后的即可。
代码
public class MyBitmap {
//每一个word是一个long类型元素,对应一个64位二进制
private long[] words;
//Bitmap的总位数大小
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
*/
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){
return bitIndex >> 6;// bitIndex / 64
}
public static void main(String[] args) {
MyBitmap myBitmap = new MyBitmap(128);
myBitmap.setBit(126);
myBitmap.setBit(75);
System.out.println(myBitmap.getBit(126));
System.out.println(myBitmap.getBit(78));
}
}
只是为了记录自己的学习历程,且本人水平有限,不对之处,请指正。
标签:00,bitIndex,标签,用户,Bitmap,巧用,size From: https://www.cnblogs.com/changming06/p/18675887