一、前言
我的第一篇blog《详谈redis数据结构》就讲到过,redis的字符串类型可以存储字符串、整数、浮点数。
注意我说的redis字符串类型和字符串,
前者是redis内部概念,1和“kelvin”都算redis的字符串类型;
后者是编程的广泛概念,1是整数,“Kelvin”这种称为字符串。
看到上面我说的redis的字符串类型可以存储字符串、整数、浮点数,作为一个学习了多种高级编程语言的你,或许会很疑惑,以一个字符串形式输入的“1”为什么又可以变为1呢(integer的1)。当用户将一个值存储到redis字符串的时候,如果这个值可以被解释为十进制整数或者浮点数,那么redis会觉察到这一点,并允许用户对这个字符串执行各种INCR和DECR操作。
我们用代码来证明一下
conn.set("age","19");
System.out.println(conn.incr("age"));
“19”是可以被解释为19的,所以可以执行自增操作。
那么如果我们对一个不能解释为整型或浮点型的数做自增自减操作呢?如下代码所示:
conn.set("age","AGE");
System.out.println(conn.incr("age"));
如上所示,不能被解释为整型或浮点型的数据类型被执行自增自减操作时会报出异常。
二、自增自减操作
2.1 对不存在的键或空键做自增自减操作
如果用户对一个不存在的键或者保存了空串的键执行自增自减操作,那么redis在执行操作时会将这个键当做是0来处理。
System.out.println(conn.get("boy"));//获取value值
System.out.println(conn.incr("boy"));//自增
System.out.println(conn.decr("boy"));//自减
如上所示,键名为“boy”的字符串的value为null,但是做自增操作时,当做0来处理,经过自增就变成1了。然后再自减,就变成0了。
2.2 可选参数增减
其实很好理解,2.1节中的自增自减都是默认以1为增减单位的。但是日常开发中不可能每次增减量都是1,所以我们可以通过这种可选参数来自定义增减量。
System.out.println(conn.get("boy"));//获取value值
System.out.println(conn.incrBy("boy",5));//自增,增量为5
System.out.println(conn.decrBy("boy",2));//自减,减量为2
对于浮点型来说,操作方式和整型其实是一致的,但是有一个小小的需要注意的地方就是,浮点型没有定义自减命令,不信你可以试试decrByFloat,编译器一定会报红
那对于浮点型来说,想实现自减,只能在自增的命令里将自增量置为负数来实现。
System.out.println(conn.get("boy"));//获取value值
System.out.println(conn.incrByFloat("boy",5.9));//自增,增量为5
System.out.println(conn.incrByFloat("boy",-2.3));//自减,减量为2
2.3 供redis处理子串和二进制的命令
2.3.1 APPEND
append 将值value追加到给定键key-name当前存储的值的末尾
System.out.println(conn.append("str-key","kel"));
//作用:将值value追加到给定键key-name当前存储的值的末尾
// 返回:字符串当前长度,3
System.out.println(conn.append("str-key","vin"));
// 返回:6
System.out.println(conn.get("str-key"));
//返回:kelvin
2.3.2 GETRANGE
获取[start,end]之间所有字符组成的子串
System.out.println(conn.set("str","KelvinLinaOscarMike"));
System.out.println(conn.getrange("str",2,10));
// 作用:获取键为"str"字符串中[2,10]之间的子串
//返回:lvinLinaO
2.3.3 SUBSTR
获取[start,end]之间所有字符组成的子串
System.out.println(conn.set("str","KelvinLinaOscarMike"));
System.out.println(conn.substr("str",2,10));
// 作用:获取键为"str"字符串中[2,10]之间的子串
//返回:lvinLinaO
GETRANGE命令是由以前SUBSTR命令改名而来,Redis2.6以上版本可通用
2.3.4 SETRANGE
将从start偏移量开始的子串设置为给定值
System.out.println(conn.set("str", "KelvinLinaOscarMike"));
System.out.println(conn.setrange("str", 2, "OOOO"));
System.out.println(conn.get("str"));
//作用,将str的字符串从索引2开始替换"OOOO"
//返回,19(当前字符串长度)
//置换后的字符串:KeOOOOLinaOscarMike
2.3.5 GETBIT
将字符串类型的value当成二进制位串来运算,从左到右,取到偏移量上的值,以Boolean类型展示
/**
* a的ASCII码为01100001
* */
System.out.println(conn.set("str", "a"));
System.out.println(conn.getbit("str", 0));
System.out.println(conn.getbit("str", 1));
System.out.println(conn.getbit("str", 2));
System.out.println(conn.getbit("str", 3));
System.out.println(conn.getbit("str", 4));
System.out.println(conn.getbit("str", 5));
System.out.println(conn.getbit("str", 6));
System.out.println(conn.getbit("str", 7));
2.3.6 SETBIT
将字符串类型的value值当成二进制位串,从左至右进行处理,将给定位偏移量上的二进制位进行变换
/**
* a的ASCII码为01100001
* b的ASCII码为01100010
* */
System.out.println(conn.set("str", "a"));
System.out.println(conn.setbit("str", 7,false));
System.out.println(conn.setbit("str", 6,true));
System.out.println(conn.get("str"));
上面的程序就是将’a’的二进制位串的索引为7的位,置为false,索引为6的位,置为true。故而‘a’就变成’b’了。
2.3.7 BITCOUNT
统计字符串的二进制位串中1的个数,如果指定[start,end]则只计算区间内的子字符串的二进制位串中1的个数
/**
* a的ASCII码为01100001,共3个1
* b的ASCII码为01100010,共3个1
* c的ASCII码为01100011,共4个1
* */
System.out.println(conn.set("str", "abc"));
System.out.println(conn.bitcount("str"));
System.out.println(conn.bitcount("str", 0,1));
System.out.println(conn.get("str"));
2.3.8 BITOP
对一个或多个二进制位串执行包括并(ADD)、或(OR)、异或(XOR)、非(NOT)下面将一一示范
并(ADD)
System.out.println(conn.set("key1", "111"));
System.out.println(conn.set("key2", "101"));
//异或操作之后得到\101,按八进制转换为65,查找ASCII表为A
//A的二进制码为01000001
System.out.println(conn.bitop(BitOP.AND,"destKey","key1","key2"));
System.out.println(conn.get("destKey"));
或(OR)
System.out.println(conn.set("key1", "111"));
System.out.println(conn.set("key2", "101"));
System.out.println(conn.bitop(BitOP.OR,"destKey","key1","key2"));
System.out.println(conn.get("destKey"));
异或(XOR)
System.out.println(conn.set("key1", "\111"));
System.out.println(conn.set("key2", "\010"));
//异或操作之后得到\101,按八进制转换为65,查找ASCII表为A
//A的二进制码为01000001
System.out.println(conn.bitop(BitOP.XOR,"destKey","key1","key2"));
System.out.println(conn.get("destKey"));
/**取码查看*/
System.out.println(conn.getbit("destKey",0));
System.out.println(conn.getbit("destKey",1));
System.out.println(conn.getbit("destKey",2));
System.out.println(conn.getbit("destKey",3));
System.out.println(conn.getbit("destKey",4));
System.out.println(conn.getbit("destKey",5));
System.out.println(conn.getbit("destKey",6));
System.out.println(conn.getbit("destKey",7));
非(NOT)
System.out.println(conn.set("key1", "A"));
//A的二进制码为01000001,做非运算之后是10111110
System.out.println(conn.bitop(BitOP.NOT,"destKey","key1"));
System.out.println(conn.get("destKey"));
System.out.println(conn.getbit("destKey",0));
System.out.println(conn.getbit("destKey",1));
System.out.println(conn.getbit("destKey",2));
System.out.println(conn.getbit("destKey",3));
System.out.println(conn.getbit("destKey",4));
System.out.println(conn.getbit("destKey",5));
System.out.println(conn.getbit("destKey",6));
System.out.println(conn.getbit("destKey",7));
在以上四种操作中因为或(OR)和并(ADD)不太会涉及到字符不可见的问题,所以就没有依次取二进制位来查看,读者有兴趣可以自己试验一下。
总结
本文着重讲解了redis中字符串的各种操作命令,由此可以看出redis的强大了吗,既可以对字符串子串进行操作,还可以对二进制位串进行操作。光知道有这些redis字符串的命令是远远不够的,但是要想充分了解redis的各种运行机制,就必须先掌握本文的操作命令。进而更加深入的理解redis的数据结构。
对Java系列知识感兴趣的朋友可以加入QQ群
慧梦软件开发技术联盟:952317701
更多系列文章在java高级程序开发微信公众号