位图实现公告已读未读

  • 场景:
    APP公告,在用户端展示需要红点标记未读
    之前有看到类似的业务场景,比如用户标签,用户签到这种都可以使用位图实现。

  • 原理
    位图就是用一个二进制数据结构,按位存储标记,举个例子,假如APP有64个用户,用户ID为自增 , 一个long类型的数据刚好64位,那么作为byte数组使用,下标0~63刚好能够表示这64个用户,每个下标对应的元素为1表示已读,0表示未读位图1

public class BitMapTest {

    public static void main(String[] args) {
        BitMap bitMap = new BitMap();
        bitMap.setBit(60);
        System.out.println(bitMap.getBit(60));
        System.out.println(bitMap.getBit(59));
    }


    static class BitMap{
        byte[] k = new byte[64] ;
        public void setBit(int id){
            k[id-1] = 1;
        }

        public Boolean getBit(int id){
            return k[id-1] == 1;
        }
    }
}

用点位运算可能看起来爽点

public class BitMapTest {

    public static void main(String[] args) {
        BitMap bitMap = new BitMap();
        bitMap.setBit(60);
        System.out.println(bitMap.getBit(60));
        System.out.println(bitMap.getBit(59));
        System.out.println(bitMap.getBit(64));
        bitMap.setBit(64);
        System.out.println(bitMap.getBit(64));
    }

    static class BitMap{
        long a = 0;
        public void setBit(long id){
            a |= ( 1L << id - 1);
        }

        public Boolean getBit(long id){
            return  (a & (1L << id - 1)) != 0;
        }
    }
}
  • 实现功能
    一个APP的用户如果只有64个,那估计都得喝西北风去了,改造下~~
public class BitMapTest {

    public static void main(String[] args) {
        BitMap bitMap = new BitMap(10000000);
        bitMap.setBit(999999);
        System.out.println(bitMap.getBit(999999));
        System.out.println(bitMap.getBit(59));
        bitMap.setBit(1);
        System.out.println(bitMap.getBit(1));
    }

    static class BitMap{
        long[] ids ;

        public BitMap(int size) {
            this.ids = new long[calculateIndex(size-1) + 1];
        }

        public void setBit(int id){
            ids[calculateIndex(id)] |= ( 1L << id - 1);
        }

        public Boolean getBit(int id){
            return  (ids[calculateIndex(id)] & (1L << id - 1)) != 0;
        }

        private int calculateIndex(int size){
            return size >> 6;
        }
    }
}

这样子一个BitMap对象就能容纳[1,9999999]个用户ID了,回到我们最开始的需求,假设有9999999 个用户,一条公告需要记录所有用户的已读未读状态,不考虑边边角角的空间,需要内存大小为:

9999999 / 8 / 1024 = 1.1920MB

至少在能接受的范围了,当然造轮子主要为了理解原理,位图的实现在redis中也有,直接来用岂不快哉!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

懒眉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值