说明
录⼊:
是将录⼊字符的String 的各个char 的ASCII码转为16进制 在通过-拼接起来,通过zadd新增 score设置为0 则会通过value 16进制进⾏排序查找
将查找的字符转换为16进制通过-拼接
start计算:通过匹配字符16进制最后以为进1算出起始16进制 再+g 包括所有起始范围end计算:通过匹配字符16进制+g 包括所有范围
然后zadd临时加⼊到redis 默认通过value排序则将匹配字符⼤概包裹起来
然后通过2个临时数据获得rank 再根据起始和结zrank获得数据 过滤掉多余的 再讲16进制转换为字符 返回
录⼊数据
//unicode编码
private String coding(String s) { char[] chars = s.toCharArray();
StringBuffer buffer = new StringBuffer(); for (char aChar : chars) {
//通过字符对应的ASCII码转换为16进制再根据-拼接起来 -4f60-7231-5e7f-5dde-30 String s1 = Integer.toString(aChar, 16); buffer.append(\"-\" + s1); }
String encoding = buffer.toString(); return encoding; }
//添加数据
public long add(Jedis con, String member, String key) { //进⾏编码 存储的是 每个字符进⾏ASCII码转换的16进制 String coding = coding(member);
//如果score为0 则会根据value来进⾏排序 Long zadd = con.zadd(key, 0, coding); return zadd; }
匹配数据
/**
* unicode解码 字符通过16进制转换为ASCII码 即可得到对应字符 *
* @param s * @return */
private String decoding(String s) { String[] split = s.split(\"-\");
StringBuffer buffer = new StringBuffer();
for (String s1 : split) {
if (!s1.trim().equals(\"\")) {
//将16进制 转换成ASCII码 ASCII码对应的字符 char i = (char) Integer.parseInt(s1, 16); buffer.append(i); } }
return buffer.toString(); }
/**
* 16进制
* ⼆进制与16进制对应 0-0 1-1 2-2 3-3 4-4 5-5- 6-6 7-7 8-8 9-9 10-a 11-b 12-c 13-d 14-e 15-f 16-g */
private static final String VALID_CHARACTERS = \"0123456789abcdefg\";
private String[] findPrefixRange(String prefix) {
int posn = VALID_CHARACTERS.indexOf(prefix.charAt(prefix.length() - 1)); //查找出前缀字符串最后⼀个字符在列表中的位置 char suffix = VALID_CHARACTERS.charAt(posn > 0 ? posn - 1 : 0); //找出前驱字符 String start = null; String end = null;
//针对于单纯查0的 没有前置了 所以不⽤拼g if (posn == 0) { start = prefix;
end = prefix + \"g\";//end拼g 把范围内的全查出来
} else {
start = prefix.substring(0, prefix.length() - 1) + suffix + 'g'; //⽣成前缀字符串的前驱字符串 end = prefix + 'g';
// 防⽌多个群成员可以同时操作有序集合,将相同的前驱字符串和后继字符串插⼊有序集合//⽣成前缀字符串的后继字符串 String identifier = UUID.randomUUID().toString(); start += identifier; end += identifier; }
return new String[]{start, end}; }
//查找数据
public List member = coding(member);//把输⼊的字符转换成16进制字符串,因为redis⾥⾯存的是每个字符对应的16进制字符串 String[] range = findPrefixRange(member); String start = range[0]; String end = range[1]; //往zset插⼊起始和结束的字符,将匹配的结果的数据包起来 con.zadd(key, 0, start); con.zadd(key, 0, end); while (true) { con.watch(key); //根据插⼊包起来的数据rank拿出启始和结束的字符 int sindex = con.zrank(key, start).intValue(); int eindex = con.zrank(key, end).intValue(); //找出两个插⼊元素的位置 int erange = Math.min(sindex + 9, eindex - 2); //因为最多展⽰10个,所以计算出结束为⽌ Transaction transaction = con.multi(); transaction.zrem(key, start); transaction.zrem(key, end); transaction.zrange(key, sindex, erange); List