【黑马点评Redis——006用户签到】

1.BitMap

1.1.什么是BitMap

Redis中的Bitmap是一种特殊的数据结构,它使用一系列位来表示一组对象的状态或者标记。

1.2.BitMap的特点

  1. 节省空间:Bitmap使用了非常紧凑的表示方式,通常情况下比使用字符串列表等其他方式节省空间。
  2. 高效的位操作:Bitmap支持高效的位级别操作,如设置、清除、统计位的数量等,这使得它非常适3合于处理大规模的标记或者状态信息。
  3. 适合于稀疏数据:即使Bitmap的位数非常大,但只有被设置为1的位会占用内存,所以即使数据稀疏,它也能够以较小的内存开销存储。
  4. 原子操作:Redis提供了一系列原子操作来操作Bitmap,这意味着多个客户端可以同时对同一个Bitmap进行操作而不会出现竞态条件。

1.2.BitMap用法

在这里插入图片描述

1.3.BitMap的应用场景

  1. 标记用户在线状态:可以使用Bitmap来表示用户是否在线。例如,可以使用用户ID作为位的索引,将在线的用户的位设置为1,离线的用户的位设置为0。
  2. 统计用户活跃度:Bitmap可以用来统计用户的活跃度,比如每天登录的用户数、每小时访问网站的用户数等。
  3. 处理布隆过滤器:Bitmap可以作为布隆过滤器的底层实现,用来快速判断某个元素是否存在于集合中。
  4. 记录用户行为:可以使用Bitmap来记录用户的行为,比如记录用户是否点击过某个广告、是否阅读过某篇文章等。
  5. 处理大规模数据的集合运算:Bitmap支持位级别的运算,可以进行交集、并集、差集等操作,因此可以用来处理大规模数据的集合运算,比如用户之间的共同兴趣、共同关注的人等

2.用户签到

2.1.正常思路

在这里插入图片描述

2.2.比较好的做法

在这里插入图片描述

2.3.案例功能

在这里插入图片描述

    @Override
    public Result sign() {
        // 1.获取当前登录用户
        Long userId = UserHolder.getUser().getId();
        // 2.获取日期
        LocalDateTime now = LocalDateTime.now();
        // 3.拼接key
        String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
        String key = USER_SIGN_KEY + userId + keySuffix;
        // 4.获取今天是本月的第几天
        int dayOfMonth = now.getDayOfMonth();
        // 5.写入Redis
        stringRedisTemplate.opsForValue().setBit(key, dayOfMonth-1,true);
        return Result.ok();
    }

2.4.签到统计

从最后一次签到开始向前统计,直到遇到第一次未签到为止,计算总的签到次数,就是连续签到天数。
在这里插入图片描述
在这里插入图片描述

    @Override
    public Result signCount() {
        // 1.获取当前登录用户
        Long userId = UserHolder.getUser().getId();
        // 2.获取日期
        LocalDateTime now = LocalDateTime.now();
        // 3.拼接key
        String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
        String key = USER_SIGN_KEY + userId + keySuffix;
        // 4.获取今天是本月的第几天
        int dayOfMonth = now.getDayOfMonth();
        // 5.获取本月截止今天为止的所有签到记录,返回的是一个十进制的数字
        List<Long> result = stringRedisTemplate.opsForValue().bitField(
                key,
                BitFieldSubCommands.create().get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(0)
        );
        if(result==null || result.isEmpty()){
            //没有任何签到结果
            return Result.ok(0);
        }
        Long num = result.get(0);
        if(num==null || num==0){
            //没有任何签到结果
            return Result.ok(0);
        }
        // 6.循环遍历
        int count = 0;
        while (true){
            // 6.1.让这个数字与1做与运算,得到数字的最后一个bit位
            // 6.2.判断这个bit位是否为0
            if((num & 1)==0){
                // 6.3.如果为0,说明未签到,结束
                break;
            }else{
                // 6.4.如果不为0,说明已签到,计数器+1
                count++;
                // 6.5.数字右移一位,抛弃最后一个bit
            }
            num >>>= 1;
        }
        return Result.ok(count);
    }
  • 10
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值