插播一点题外话,这篇文章用到的东西网上屡见不鲜,也有很多很详细的内容,这里仅作我个人的理解小天地,记录一些遇到困惑的问题
关于签到功能
这里我想记录的是setBit的时候,要使用当前日期-1天作为签到时间,当然设计思路不同也可以和我不同,但是通过理解bitMap底层对于数据结构的设计我理解到这个无符号的位图,0位可以用来存储数据,而不像其他二进制数要考虑首位代表正负符号的问题
LocalDate now = LocalDate.now();
String format = now.format(DateTimeFormatter.ofPattern("yyyyMM"));
int dayOfMonth = now.getDayOfMonth();
String key = BIT_KEY + ":" + format;
//签到时间应该是当天-1 因为位图中0位是起手位
redisTemplate.opsForValue().setBit(key, dayOfMonth - 1, Boolean.TRUE);
关于累计连续签到天数的统计
这里也是从我们掘金平台的一位大佬的文章那里学习到的思路,加以理解后打开了我愚钝的脑袋装进去了些东西
LocalDate now = LocalDate.now();
String format = now.format(DateTimeFormatter.ofPattern("yyyyMM"));
// 截至今天为止,前面签到了多少天
int dayOfMonth = now.getDayOfMonth();
String key = BIT_KEY + ":" + format;
List<Long> result = redisTemplate.opsForValue().bitField(
key,
BitFieldSubCommands.create()
.get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(0));
System.out.println("result = " + result);
//没有任务签到结果
if (result == null || result.isEmpty()) {
return;
}
Long num = result.get(0);
if (num == null || num == 0) {
return;
}
int count = 0;
//如果为0,签到结束
while ((num & 1) != 0) {
// 让这个数字与1 做与运算,得到数字的最后一个bit位 判断这个数字是否为0
count++;
// 为了不影响index=0的变化 使用无符号右移 >>>
num >>>= 1;
}
System.out.println("count = " + count);
-----------这里是分割线------------
这里引入一张Redis官网文档给出的BitField的指令功能集:
我们在本功能中用到的就是Get指令,关于encoding这个参数,根据我后续使用后发现,它代表你要传入一个需要截取的位数,比如我们传入7,offset参数我们传入0,按我key的理念,就是本月的1日到7日这七天的签到统计。
所以我这里想记录并说明的是:
- BitField在RedisTemplate中,valueAt方法的作用是记录你选择的起始位;
- get方法中
BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)
的功能是选择一个需要截取的无符号位数
以上就是我本次的分享,感谢大家阅读,也请各位大佬及时建议和指正!