Bitmap的巧用

题目

关于用户标签的需求:用户标签包括用户的社会属性、生活习惯、消费行为等信息。例如,程序员,有驾照,单身等等。通过用户标签,可以对多样的用户群体进行统计。例如,统计用户的男女比例,统计喜欢旅游的用户数量等。

通常的思路,是使用关系型数据库,比如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));
    }

}

只是为了记录自己的学习历程,且本人水平有限,不对之处,请指正。

posted @   长名06  阅读(80)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~
点击右上角即可分享
微信分享提示