Java中实现签到,你会用哪种方式呢?

226 阅读2分钟

插播一点题外话,这篇文章用到的东西网上屡见不鲜,也有很多很详细的内容,这里仅作我个人的理解小天地,记录一些遇到困惑的问题

关于签到功能

这里我想记录的是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的指令功能集:

image.png 我们在本功能中用到的就是Get指令,关于encoding这个参数,根据我后续使用后发现,它代表你要传入一个需要截取的位数,比如我们传入7,offset参数我们传入0,按我key的理念,就是本月的1日到7日这七天的签到统计。

所以我这里想记录并说明的是:

  1. BitField在RedisTemplate中,valueAt方法的作用是记录你选择的起始位;
  2. get方法中BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)的功能是选择一个需要截取的无符号位数

以上就是我本次的分享,感谢大家阅读,也请各位大佬及时建议和指正!