南京网站外包,网站index.php被修改,中小企业网络拓扑图绘制,广州安全教育平台登录入口账号写在开头
本文参考原文
BitMap
Redis中的BitMap同我们所使用的算法当中的bitmap是相同的道理。简单来说就是使用二进制位#xff0c;每一位的0/1状态表示信息。 二进制表示的优势#xff1a; 大大节省空间。如两位二进制位00、01、10、11可以表示四种状态
Redis当中提供了…写在开头
本文参考原文
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表示提交次数所以offsetdate每次移动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 0000000binaryString;}else if(binaryString.length() 2){binaryString 000000binaryString;}else if(binaryString.length() 3){binaryString 00000binaryString;}else if(binaryString.length() 4){binaryString 0000binaryString;}else if(binaryString.length() 5){binaryString 000binaryString;}else if(binaryString.length() 6){binaryString 00binaryString;}else if(binaryString.length() 7){binaryString 0binaryString;}}char[] chars binaryString.toCharArray();for (int j 0; j chars.length; j) {// 设置BitMapredisUtils.setBit(CommonConstant.KEY,i*8j,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 ListString getPushData() {ListString res new ArrayList(366);// 没有数据就先造数据genTestData();int days getDays();for(long i0;idays;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 typetext/javascriptvar 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,k0; 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