Redis当中的BitMap,实现github打卡功能

写在开头

本文参考原文

BitMap

Redis中的BitMap同我们所使用的算法当中的bitmap是相同的道理。简单来说就是使用二进制位,每一位的0/1状态表示信息。
二进制表示的优势:
大大节省空间。如两位二进制位00、01、10、11可以表示四种状态

Redis当中提供了bitmap的数据结构,并有相关的操作命令。通过这命令的搭配,可以实现不同的逻辑应用。

Redis中BitMap命令

Redis提供了SETBIT、GETBIT、BITCOUNT、BITOP四个常用命令用于处理二进制位数组。

SETBIT:为位数组指定偏移量上的二进制位设置值,偏移量从0开始计数,二进制位的值只能为0或1。返回原位置值。 GETBIT:获取指定偏移量上二进制位的值。 BITCOUNT:统计位数组中值为1的二进制位数量。 BITOP:对多个位数组进行按位与、或、异或、取反运算(对应具体的操作为:ADD、OR、XOR,还有NOT)。

具体例子如下:


127.0.0.1:6379> SETBIT first 0 1    # 0000 0001
(integer) 0
127.0.0.1:6379> SETBIT first 3 1    # 0000 1001
(integer) 0
127.0.0.1:6379> SETBIT first 0 0    # 0000 1000
(integer) 1127.0.0.1:6379> GETBIT first 0
(integer) 0
127.0.0.1:6379> GETBIT first 3
(integer) 1127.0.0.1:6379> BITCOUNT first      # 0000 1000
(integer) 1
127.0.0.1:6379> SETBIT first 0 1    # 0000 1001
(integer) 0
127.0.0.1:6379> BITCOUNT first      # 0000 1001
(integer) 2
127.0.0.1:6379> SETBIT first 1 1    # 0000 1011
(integer) 0
127.0.0.1:6379> BITCOUNT first      # 0000 1011
(integer) 3127.0.0.1:6379> SETBIT x 3 1        
(integer) 0
127.0.0.1:6379> SETBIT x 1 1        
(integer) 0
127.0.0.1:6379> SETBIT x 0 1        # 0000 1011
(integer) 0
127.0.0.1:6379> SETBIT y 2 1        
(integer) 0
127.0.0.1:6379> SETBIT y 1 1        # 0000 0110
(integer) 0
127.0.0.1:6379> SETBIT z 2 1        
(integer) 0
127.0.0.1:6379> SETBIT z 0 1        # 0000 0101
(integer) 0127.0.0.1:6379> BITOP AND andRes x y z    #0000 0000
(integer) 1
127.0.0.1:6379> BITOP OR orRes x y z      #0000 1111
(integer) 1
127.0.0.1:6379> BITOP XOR x y z           #0000 1000
(integer) 1# 对给定的位数组进行按位取反
127.0.0.1:6379> SETBIT value 0 1
(integer) 0
127.0.0.1:6379> SETBIT value 3 1            #0000 1001
(integer) 0
127.0.0.1:6379> BITOP NOT notValue value    #1111 0110
(integer) 1

具体每种命令的详解可见参考原文。

实现github打卡功能

功能分析:

GitHub当中的打卡签到为一年,每天提交的次数决定了当前天签到颜色的深浅。
向bitmap的结构中思考。
1、我们对于每个用户,都有一个打卡表,所以可以将用户的唯一标识作为bitmap的key,当前是哪一天作为bitmap的offset,提交次数作为bit。
2、按照以上思考的大概是没问题的,但是我们的提交次数肯定不能只限定在0次或1次。
3、所以解决此问题的方法,就是我们多使用几位bit来表示提交次数,并且,因为多使用了几位bit,需要我们在设置offset也就是日期,做相应的逻辑转换。

整体的逻辑为:set userID Date times
使用一个字节(8bit)表示提交次数,所以offset(date)每次移动8位
如:0000 0011 0000 1011,后八位表示一天(如11月26日),提交次数为11次,前八位表示相邻一天(11月27日)提交次数3次

代码实现:

生成模拟数据

public void genTestData() {if(redisUtils.isExist(CommonConstant.KEY)){return;}// 获取当前年的总天数int days = getDays();for (int i = 0; i < days; i++) {int random = ThreadLocalRandom.current().nextInt(64);// 生成随机数表示每天的PR次数String binaryString = Integer.toBinaryString(random);if (binaryString.length() < 8) {// 填充0if(binaryString.length() == 0){binaryString = "00000000";}else if(binaryString.length() == 1){binaryString = "0000000"+binaryString;}else if(binaryString.length() == 2){binaryString = "000000"+binaryString;}else if(binaryString.length() == 3){binaryString = "00000"+binaryString;}else if(binaryString.length() == 4){binaryString = "0000"+binaryString;}else if(binaryString.length() == 5){binaryString = "000"+binaryString;}else if(binaryString.length() == 6){binaryString = "00"+binaryString;}else if(binaryString.length() == 7){binaryString = "0"+binaryString;}}char[] chars = binaryString.toCharArray();for (int j = 0; j < chars.length; j++) {// 设置BitMapredisUtils.setBit(CommonConstant.KEY,i*8+j,chars[j]);}}
}/*** 获取当前年的总天数* @return days 总天数*/
private int getDays(){Calendar calOne = Calendar.getInstance();int year = calOne.get(Calendar.YEAR);System.out.println(year);Calendar calTwo = new GregorianCalendar(year, 11, 31);return calTwo.get(Calendar.DAY_OF_YEAR);
}

获取Redis bitmap中的数据

public List<String> getPushData() {List<String> res = new ArrayList<>(366);// 没有数据就先造数据genTestData();int days = getDays();for(long i=0;i<days;i++){StringBuilder sb = new StringBuilder();for (int j = 0; j < 8; j++) {String bit = redisUtils.getBit(CommonConstant.KEY, i * 8 + j);sb.append(bit);}// 直接返回二进制串,前端转换为十进制res.add(sb.toString());}return res;
}

前端展示

<script type="text/javascript">var chartDom = document.getElementById('main');var myChart = echarts.init(chartDom);var option;function getVirtulData(year) {var date = +echarts.number.parseDate(year + '-01-01');var end = +echarts.number.parseDate(+year + 1 + '-01-01');var dayTime = 3600 * 24 * 1000;var data = [];$.ajax({"url":'http://localhost:8080/test/getPushData',"async":false, // ajax同步获取success:function (res){for (let time = date,k=0; time < end && k < res.data.length; time += dayTime,k++) {data.push([echarts.format.formatTime('yyyy-MM-dd', time),parseInt(res.data[k],2)//客户端完成进制转换,不放在服务端完成]);}}})return data;}option = {title: {top: 30,left: 'left',text: 'BitMap Demo'},tooltip: {},visualMap: {min: 0,max: 32,type: 'piecewise',orient: 'horizontal',left: 'right',top: 220,pieces: [{min: 0, max: 0,label:"less"},{min: 1, max: 10,label:" "},{min: 1, max: 20,label:" "},{min: 21, max: 40,label:" "},{min: 41, max: 64,label:"more"},],inRange: {color: [ '#EAEDF0', '#9AE9A8', '#41C363', '#31A14E', '#206D38' ],//颜色设置 colorAlpha: 0.9,//透明度}},calendar: {top: 120,left: 30,right: 30,cellSize: 13,range: '2022',splitLine: { show: false },//不展示边线itemStyle: {borderWidth: 0.5},yearLabel: { show: false }},series: {type: 'heatmap',coordinateSystem: 'calendar',data: getVirtulData('2022')}};option && myChart.setOption(option);
</script>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/171360.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

css优化滚动条样式

css代码&#xff1a; ::-webkit-scrollbar {width: 6px;height: 6px; }::-webkit-scrollbar-track {background-color: #f1f1f1; }::-webkit-scrollbar-thumb {background-color: #c0c0c0;border-radius: 3px; }最终样式&#xff1a;

华为OD机试真题-围棋的气-2023年OD统一考试(C卷)

题目描述: 围棋棋盘由纵横各19条线垂直相交组成,棋盘上一共19x19=361个交点,对弈双方一方执白棋,一方执黑棋,落子时只能将棋子置于交点上。 “气”是围棋中很重要的一个概念,某个棋子有几口气,是指其上下左右方向四个相邻的交叉点中,有几个交叉点没有棋子,由此可知: …

TPLink-Wr702N 通过OpenWrt系统打造打印服务器实现无线打印

最近淘到了一个TPLink-Wr702N路由器&#xff0c;而且里面已经刷机为OpenWrt系统了&#xff0c;刚好家里有一台老的USB打印机&#xff0c;就想这通过路由器将打印机改为无线打印机&#xff0c;一番折腾后&#xff0c;居然成功了&#xff0c;这里记录下实现过程&#xff0c;为后面…

flink源码分析之功能组件(二)-kubeclient

简介 本系列是flink源码分析的第二个系列,上一个《flink源码分析之集群与资源》分析集群与资源,本系列分析功能组件,kubeclient,rpc,心跳,高可用,slotpool,rest,metrics,future。其中kubeclient上一个系列介绍过,为了系列完整性,这里“copy”一下。 kubeclient组件…

electron+vue3全家桶+vite项目搭建【26】electron本地安装Vue Devtool插件,安装浏览器扩展

文章目录 引入获取vue devtool导入插件排除插件的npm脚本最终效果 引入 demo项目地址 Vue Devtools插件是vue项目必备插件&#xff0c;它是安装在浏览器里的&#xff0c;而咱们的electron中实际就包含了一个浏览器&#xff0c;同理它也可以加载浏览器插件 获取vue devtool 直…

【开源】基于Vue+SpringBoot的食品生产管理系统

项目编号&#xff1a; S 044 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S044&#xff0c;文末获取源码。} 项目编号&#xff1a;S044&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 加工厂管理模块2.2 客户管理模块2.3…

WIFI模块(esp-01s)获取网络时间与天气信息

目录 一、硬件连接 二、获取网络时间 1、AT指令集 2、具体操作 三、获取天气信息 1、心知天气注册 2、AT指令集 3、具体操作 4、json格式检查 一、硬件连接 WiFi模块的RX连接TTL模块的TX&#xff0c; WiFi模块的TX连接TTL模块的RX&#xff0c;电源与地接对。 插入电脑…

Python 安装Vue依赖包发生异常:npm ERR! notsup Required: {“node“:“^18.17.0 || >=20.5.0“}

异常&#xff1a; 原因&#xff1a;node和npm要求升级为高版本 解决&#xff1a;重新安装node环境 &#xff08;1&#xff09; 官网下载Node.js &#xff08;2&#xff09;双击安装node.js &#xff08;3&#xff09;运行查看

智能优化算法应用:基于蝗虫算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于蝗虫算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于蝗虫算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.蝗虫算法4.实验参数设定5.算法结果6.参考文献7.MATLAB…

第二十一章 解读XML与JSON文件格式(工具)

XML 带分隔符的文件仅有两维的数据&#xff1a;行 & 列。如果我们想在程序之间交换数据结构&#xff0c;需要一种方法把层次结构&#xff0c;序列&#xff0c;集合和其它的数据结构编码成文本。 今天要说的 XML 是最突出的处理上述这种转换的标记格式&#xff0c;它使用标…

每日一题2023.11.26——个位数统计【PTA】

题目要求&#xff1a; 输入格式&#xff1a; 每个输入包含 1 个测试用例&#xff0c;即一个不超过 1000 位的正整数 N。 输出格式&#xff1a; 对 N 中每一种不同的个位数字&#xff0c;以 D:M 的格式在一行中输出该位数字 D 及其在 N 中出现的次数 M。要求按 D 的升序输出。…

2. 流程控制|方法|数组|二维数组|递归

文章目录 流程控制代码块选择结构循环结构跳转控制关键字 方法方法的概述方法的重载Junit单元测试初识全限定类名 Debug 小技巧数组数组的基本概念数组的基本使用数组的声明数组的初始化 JVM内存模型什么是引用数据类型基本数据类型和引用数据类型的区别堆和栈中内容的区别 数组…

PTA NeuDs_数据库题目

二.单选题 1.数据库应用程序的编写是基于数据库三级模式中的。 A.模式 B.外模式 C.内模式 D.逻辑模式 用户应用程序根据外模式进行数据操作&#xff0c;通过外模式一模式映射&#xff0c;定义和建立某个外模式与模式间的对应关系 2.对创建数据库模式一类的数据库对象的授权…

Typescript基础面试题 | 02.精选 ts 面试题

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

智能优化算法应用:基于海鸥算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于海鸥算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于海鸥算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.海鸥算法4.实验参数设定5.算法结果6.参考文献7.MATLAB…

痤疮分级实验笔记-ResNet

组织数据集 方式1&#xff1a;根据txt文件分类的数据集组织形式&#xff08;放弃&#xff09; 你可以使用Python来读取txt文件中的训练集图片信息&#xff0c;并将这些图片从原始文件夹复制到目标文件夹中。 当程序无法找到标签对应的图片或者目标文件夹中已经存在同名图片时…

C语言编译过程再解析

多年以前,分析过编译过程,并写了一篇博客,现在对编译过程有了更广阔的认识,记录在此 编译过程 中的 链接与 编译 编译过程分为1. 预处理2. 编译3. 汇编4. 链接其中有 2个过程比较特殊,1. 编译2. 链接对于C程序来说,链接分为提前链接(静态链接)对应下图第1行运行时链接(动态链…

QGIS安装及简单使用

QGIS&#xff08;Quantum GIS&#xff09;是一个自由、开源的跨平台桌面地理信息系统&#xff08;GIS&#xff09;应用程序&#xff0c;它允许用户创建、编辑、查看、分析和发布地理空间数据和地图。 操作系统&#xff1a;Windows 10 QGIS版本&#xff1a;QGIS Desktop 3.28.…

【二叉树】oj题

在处理oj题之前我们需要先处理一下之前遗留的问题 在二叉树中寻找为x的节点 BTNode* BinaryTreeFind(BTNode* root, int x) {if (root NULL)return NULL;if (root->data x)return root;BTNode* ret1 BinaryTreeFind(root->left, x);BTNode* ret2 BinaryTreeFind(ro…

【华为OD】B\C卷真题:100%通过:找城市 C/C++实现

【华为OD】B\C卷真题&#xff1a;100%通过&#xff1a;找城市 C/C实现 题目描述&#xff1a; 一张地图上有n个城市&#xff0c;城市和城市之间有且只有一条道路相连&#xff1a;要么直接相连&#xff0c;要么通过其它城市中转相连&#xff08;可中转一次或多次&#xff09;。…