Redis的基本操作总结

563 阅读14分钟

一、RedisTemplate的操作

Common

(1)haskey

//判断是否有key=a,返回布尔值
Boolean result = redisTemplate.hasKey("a");
System.out.println(result);//true

(2)getExpire

redisTemplate.opsForValue().set("a","aa");
//获取key=a的剩余过期时间 如果过期了 返回负数(-2) 未过期 默认返回剩余秒数
Long a = redisTemplate.getExpire("a");
System.out.println(a);//-1
//获取key=a的剩余过期时间 如果过期了 返回负数(-2)
//未过期 按照设置的单位返回 但是如果比如未满1min,会返回0,依次类推
System.out.println(redisTemplate.getExpire("a", TimeUnit.MINUTES));//-1

(3)delete

redisTemplate.opsForValue().set("a","aa");
//删除key,如果没有key或者删除失败,返回false 也可以批量删除
Boolean result = redisTemplate.delete("f");
System.out.println(result);//false

(4)dump

redisTemplate.opsForValue().set("a","aa");
//将key值序列化为byte[]类型
byte[] as = redisTemplate.dump("a");
System.out.println(as);//[B@5ffa6f

(5)randomKey

redisTemplate.opsForValue().set("a","aa");
//随机返回一个key值
String s = redisTemplate.randomKey();
System.out.println(s);//a

(6)type

redisTemplate.opsForValue().set("a","aa");
//返回key的类型 STRING
DataType a = redisTemplate.type("a");
System.out.println(a);//STRING

(7)rename

redisTemplate.opsForValue().set("a","aa");
//将key=a重命名为b, a=null b=a旧值
redisTemplate.rename("a","b");
System.out.println(redisTemplate.opsForValue().get("a"));//null
System.out.println(redisTemplate.opsForValue().get("b"));//aa

(8)move

redisTemplate.opsForValue().set("a","aa");
//将key=b移入到库编号2中
Boolean result = redisTemplate.move("a", 2);
System.out.println(result);//true

(9)persist

redisTemplate.opsForValue().set("a","aa");
//将a持久化保存
Boolean result = redisTemplate.persist("a");
System.out.println(result);//false

1.String

(1)设置值

//设置a的值
redisTemplate.opsForValue().set("a","abcd");//set a 1
//原子的操作,设置值,返回旧值
redisTemplate.opsForValue().getAndSet("f", "fff");

(2)获取值

redisTemplate.opsForValue().set("a","abcd");//set a 1
//获取a的值 没有就返回null
Object a = redisTemplate.opsForValue().get("a");//get a
//返回子字符串 需要从0开始 比如下面的例子就返回 "abcd"
System.out.println(redisTemplate.opsForValue().get("f", 0, 8));

(3)过期时间设置

//设置b的值为2,过期时间为1s
//方法1
redisTemplate.opsForValue().set("b","2",1, TimeUnit.SECONDS);
//方法2
redisTemplate.opsForValue().set("b","2");
//设置b的过期时间为2s
redisTemplate.expire("b", 2, TimeUnit.SECONDS);
//如果没有过期查询返回正常的值,如果过期了,返回null
redisTemplate.opsForValue().get("b");
//获取key=b的剩余过期时间 如果过期了 返回负数(-2) 未过期 默认返回剩余秒数 key存在key没有设置过期时间返回-1
redisTemplate.getExpire("b");
//获取key=b的剩余过期时间 如果过期了 返回负数(-2)
//未过期 按照设置的单位返回 但是如果比如未满1min,会返回0,依次类推
redisTemplate.getExpire("b", TimeUnit.MINUTES);

(4)自增、自减

redisTemplate.opsForValue().set("c",1);
//给值c加2 这里要注意set的时候,value必须为数值型,整型的如 "1" 会报错。
redisTemplate.opsForValue().increment("c", 2);
//给值c减3
redisTemplate.opsForValue().decrement("c", 3);

(5)批量自增、自减

Map map = new HashMap();
map.put("d", "1");
map.put("e", "2");
//批量set
redisTemplate.opsForValue().multiSet(map);

List<String> str = new ArrayList<>();
str.add("d");
str.add("e");
//批量get,返回list
redisTemplate.opsForValue().multiGet(str);

2.List

(1)头部添加一个/多个元素

//[单个]返回值为索引值 (索引值从1开始算)
Long alist = redisTemplate.opsForList().leftPush("alist", "1");
System.out.println(alist);//1

//[多个]返回值为索引值 (索引值从1开始算) 存储多个返回的是存储的最后一个索引值
List<String> listTemp = new ArrayList<>();
listTemp.add("1");
listTemp.add("2");
listTemp.add("3");
Long alist = redisTemplate.opsForList().leftPushAll("alist", listTemp);
System.out.println(alist);//1 存入的值是["java.util.ArrayList",["1","2","3"]] 对象
Long blist = redisTemplate.opsForList().leftPushAll("alist", listTemp.toArray());
System.out.println(blist);//4 存入的值是 1 2 3字符串
Long clist = redisTemplate.opsForList().leftPushAll("alist", new String[]{"4","5","6"});
System.out.println(clist);//7 存入的值是 4 5 6字符串

(2)尾部添加一个/多个元素

//[单个]返回值为索引值 (索引值从1开始算)
Long alist = redisTemplate.opsForList().rightPush("alist", "2");
System.out.println(alist);//2

//[多个]返回值为索引值 (索引值从1开始算) 存储多个返回的是存储的最后一个索引值
List<String> listTemp = new ArrayList<>();
listTemp.add("1");
listTemp.add("2");
listTemp.add("3");
Long alist = redisTemplate.opsForList().rightPushAll("blist", listTemp);
System.out.println(alist);//1 存入的值是["java.util.ArrayList",["1","2","3"]]
Long blist = redisTemplate.opsForList().rightPushAll("blist", listTemp.toArray());
System.out.println(blist);//4 存入的值是 1 2 3字符串
Long clist = redisTemplate.opsForList().rightPushAll("blist", new String[]{"4","5","6"});
System.out.println(clist);//7 存入的值是 4 5 6字符串

Long clist = redisTemplate.opsForList().rightPushAll("clist", "2", "7");//2 此时list为[2,7]
System.out.println(clist);

(3)获取列表中单个元素

//通过索引获取列表中元素value 假设此时列表中元素为[1,2] 索引值从0开始算
Object value1 = redisTemplate.opsForList().index("alist", 0L);
System.out.println(value1);//1
Object value2 = redisTemplate.opsForList().index("alist", 1L);
System.out.println(value2);//2
Object value3 = redisTemplate.opsForList().index("alist", 2L);
System.out.println(value3);//null

(4)获取列表中多个元素

//通过索引获取列表中元素value 假设此时列表中元素为[1,2]
List<Object> alist = redisTemplate.opsForList().range("alist", 0L, 1L);
System.out.println(alist);//[1, 2]
List<Object> blist = redisTemplate.opsForList().range("alist", 0L, 2L);
System.out.println(blist);//[1, 2]
List<Object> clist = redisTemplate.opsForList().range("blist", 0L, 1L);
System.out.println(clist);//[] blist不存在 返回空list
List<Object> dlist = redisTemplate.opsForList().range("alist", 0, -1);
System.out.println(dlist);//[1, 2] -1代表获取所有元素
List<Object> elist = redisTemplate.opsForList().range("alist", 1, -1);
System.out.println(elist);//[2] -1代表获取所有元素

(5)如果存在key才会存储

//返回值为索引值 (索引值从1开始算)
Long alist = redisTemplate.opsForList().leftPushIfPresent("alist", "1");
System.out.println(alist);//0 alist不存在的时候不会存且返回值为0
Long blist = redisTemplate.opsForList().leftPush("alist", "1");
System.out.println(blist);//1
Long clist = redisTemplate.opsForList().leftPushIfPresent("alist", "2");
System.out.println(clist);//2

(6)如果pivot处值存在则在pivot前面添加

//pivot语法 redisTemplate.opsForList().leftPush(key, pivot, value)
//返回值为索引值 (索引值从1开始算) 此时list为[1,1,2,3]
Long alist = redisTemplate.opsForList().leftPush("alist", 1,"4");
System.out.println(alist);//-1 此处1是数值型 不等于字符串"1" 返回-1代表值不存在且没存储进去
Long blist = redisTemplate.opsForList().leftPush("alist", "1","4");
System.out.println(blist);//5 此时list为[4,1,1,2,3] 返回的是整个list的长度 可以看到重复的就选择第一个的去添加且只添加1次
Long clist = redisTemplate.opsForList().leftPush("alist", "2","6");
System.out.println(clist);//6 此时list为[4,1,1,6,2,3]
Long dlist = redisTemplate.opsForList().rightPush("alist", "2","7");
System.out.println(dlist);//7 此时list为[4,1,1,6,2,7,3]
Long elist = redisTemplate.opsForList().rightPush("alist", "1","8");
System.out.println(elist);//8 此时list为[4,1,8,1,6,2,7,3] 遇到重复的1的时候,仍然选择第一个1的右侧去插入

(7)修改某索引的值

//此时blist为[1,2] 索引从0开始算
redisTemplate.opsForList().set("blist", 1, "7");//修改后的list = [1,7]
//io.lettuce.core.RedisCommandExecutionException: ERR index out of range
redisTemplate.opsForList().set("blist", 5, "8");//数组越界会报错

(8)获取列表中元素个数

Long blist = redisTemplate.opsForList().size("blist");
System.out.println(blist);//2 索引不存在的话返回0

(9)裁剪列表

//原list [4,3,1,2] 索引从0开始算 无返回值
redisTemplate.opsForList().trim("blist",1,2);
//裁剪后的list [3,1]

(10)从列表中删除某个值的元素

//删除集合中值等于value的元素(index=0, 删除所有值等于value的元素; 
//index>0, 从头部开始删除前N个值等于value的元素; index<0, 从尾部开始删除前N个等于value的元素)
//语法 redisTemplate.opsForList().remove(key, index, value)
//原list [1,5,1,4,1,2,3,1,6]
Long blist = redisTemplate.opsForList().remove("blist", 2, "0");
System.out.println(blist);//0 代表删除的个数
System.out.println(redisTemplate.opsForList().range("blist", 0, 9));//[1, 5, 1, 4, 1, 2, 3, 1, 6]
Long clist = redisTemplate.opsForList().remove("blist", 2, "1");
System.out.println(clist);//2
System.out.println(redisTemplate.opsForList().range("blist", 0, 9));//[5, 4, 1, 2, 3, 1, 6]
Long dlist = redisTemplate.opsForList().remove("blist", -3, "1");
System.out.println(dlist);//2
System.out.println(redisTemplate.opsForList().range("blist", 0, 9));//[5, 4, 2, 3, 6]
Long elist = redisTemplate.opsForList().remove("blist", 0, "1");
System.out.println(elist);//0
System.out.println(redisTemplate.opsForList().range("blist", 0, 9));//[5, 4, 2, 3, 6]

(11)从左侧/右侧移除并获取列表中第一个元素

//从左侧/右侧移除并获取列表中第一个元素(如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止)
//原list为 [5,4,2,3,6]
Object value = redisTemplate.opsForList().leftPop("blist");
System.out.println(value);//5
Object value2 = redisTemplate.opsForList().rightPop("blist");
System.out.println(value2);//6
Object value3 = redisTemplate.opsForList().leftPop("blist", 2, TimeUnit.SECONDS);
System.out.println(value3);//4
Object value4 = redisTemplate.opsForList().rightPop("blist", 1, TimeUnit.SECONDS);
System.out.println(value4);//3
Object value5 = redisTemplate.opsForList().leftPop("blist");
System.out.println(value5);//2 此时list中没有元素了
//第一种情况: io.lettuce.core.RedisCommandTimeoutException: Command timed out 可以通过调整yml配置文件中redis的timeout配置
//第二种情况: 2s之后 继续执行下面的代码
Object value6 = redisTemplate.opsForList().leftPop("blist", 2, TimeUnit.SECONDS);
System.out.println(value6);//null
//此时list中已经没有元素了 java代码会直接不停留往下运行
Object value7 = redisTemplate.opsForList().leftPop("blist");
System.out.println(value7);//null

(12)从一个队列的右边弹出一个元素并将这个元素放入另一个指定队列的最左边

//从一个队列的右边弹出一个元素并将这个元素放入另一个指定队列的最左边

//从alist列表的右侧弹出一个元素并放到blist列表的左侧
//第一种情况 alist无元素 blist无元素 结果是 null
//第二种情况 alist有元素 blist无元素 结果是 新建blist列表并把alist中的元素存入blist中
//第三种情况 alist无元素 blist有元素 结果是 null
//第四种情况 alist有元素 blist有元素 结果是 完成元素的交换 如果alist只有一个元素 alist列表会被删除
Object value = redisTemplate.opsForList().rightPopAndLeftPush("alist","blist");
System.out.println(value);//返回alist中弹出的元素值 如果没有返回null

//结果情况基本同上 如果结果是null 会等待2s再继续执行
Object value2 = redisTemplate.opsForList().rightPopAndLeftPush("alist","blist",2,TimeUnit.SECONDS);
System.out.println(value2);//返回alist中弹出的元素值 如果没有返回null

3.Hash

(1)单个/多个添加

//单个添加
redisTemplate.opsForHash().put("ahash","a","1");
Map<String, String> map = new HashMap<>();
map.put("b", "2");
map.put("c", "3");
map.put("d", "4");
//多个添加
redisTemplate.opsForHash().putAll("ahash",map);
Map<Object, Object> ahash = redisTemplate.opsForHash().entries("ahash");
System.out.println(ahash);//{a=1, b=2, c=3, d=4}

(2)单个/多个field-value获取

//ahash中数据 {a=1, b=2, c=3, d=4}
//单个查询
Object value1 = redisTemplate.opsForHash().get("ahash", "a");
System.out.println(value1);//1
Object value2 = redisTemplate.opsForHash().get("ahash", "e");
System.out.println(value2);//null

//获取该key下所有field-value
Map<Object, Object> valueMap = redisTemplate.opsForHash().entries("ahash");
System.out.println(valueMap);//{a=1, b=2, c=3, d=4}
Map<Object, Object> valueMap1 = redisTemplate.opsForHash().entries("bhash");
System.out.println(valueMap1);//{}

//多个查询
//当前ahash 数据为{d=4,e=5} chash不存在
List<Object> list = new ArrayList<>();
list.add("d");
list.add("e");
list.add("f");
List<Object> ahash = redisTemplate.opsForHash().multiGet("ahash", list);
System.out.println(ahash);//[4, 5, null] 注意此时size = 3
List<Object> chash = redisTemplate.opsForHash().multiGet("chash", list);
System.out.println(chash);//[null, null, null] 注意此时size = 3

(3)获取该key下所有的field

//ahash中数据 {a=1, b=2, c=3, d=4}
//获取该key下所有的field
Set<Object> ahashSet = redisTemplate.opsForHash().keys("ahash");
System.out.println(ahashSet);//[a, b, c, d]
Set<Object> ahashSet1 = redisTemplate.opsForHash().keys("bhash");
System.out.println(ahashSet1);//[]

(4)获取该key下所有的value

//ahash中数据 {a=1, b=2, c=3, d=4}
//获取该key下所有的value
List<Object> ahashList = redisTemplate.opsForHash().values("ahash");
System.out.println(ahashList);//[1, 2, 3, 4]
List<Object> ahashList1 = redisTemplate.opsForHash().values("bhash");
System.out.println(ahashList1);//[]

(5)根据field是否存在判断是否设置

//ahash中数据 {a=1, b=2, c=3, d=4, e=5}
//如果该key下的field没有 那么会正常存储进去 返回true 如果该field存在 不管value是否为新值 结果都返回false
//如果该key不存在 那么会新建该key并正常存值
Boolean aBoolean = redisTemplate.opsForHash().putIfAbsent("ahash", "e", "5");
System.out.println(aBoolean);//false
Boolean bBoolean = redisTemplate.opsForHash().putIfAbsent("bhash", "a", "1");
System.out.println(bBoolean);//false
Boolean cBoolean = redisTemplate.opsForHash().putIfAbsent("ahash", "e", "5");
System.out.println(cBoolean);//false
Boolean dBoolean = redisTemplate.opsForHash().putIfAbsent("bhash", "a", "2");
System.out.println(dBoolean);//false

(6)判断当前key下的field的是否存在

//ahash中数据 {a=1, b=2, c=3, d=4, e=5} chash不存在
Boolean aBoolean = redisTemplate.opsForHash().hasKey("ahash","a");
System.out.println(aBoolean);//true
Boolean bBoolean = redisTemplate.opsForHash().hasKey("ahash", "f");
System.out.println(bBoolean);//false
Boolean cBoolean = redisTemplate.opsForHash().hasKey("chash", "a");
System.out.println(cBoolean);//false

(7)查询当前key下field-value的个数

//ahash中数据 {a=1, b=2, c=3, d=4, e=5} chash不存在
Long ahash = redisTemplate.opsForHash().size("ahash");
System.out.println(ahash);//5
Long chash = redisTemplate.opsForHash().size("chash");
System.out.println(chash);//0

(8)删除/批量删除

//ahash中数据 {a=1, b=2, c=3, d=4, e=5} bhash {a=1}  chash不存在
Long ahash = redisTemplate.opsForHash().delete("ahash","a");
System.out.println(ahash);//1 返回值代表删除的数量
Long ahash1 = redisTemplate.opsForHash().delete("ahash","a","b","c");
System.out.println(ahash1);//2
Long ahash2 = redisTemplate.opsForHash().delete("ahash","f");
System.out.println(ahash2);//0
Long ahash3 = redisTemplate.opsForHash().delete("chash","a");
System.out.println(ahash3);//0
//java.lang.IllegalArgumentException: Fields must not be empty
Long bhash = redisTemplate.opsForHash().delete("bhash");
System.out.println(bhash);
//java.lang.IllegalArgumentException: Fields must not be empty
Long chash = redisTemplate.opsForHash().delete("chash");
System.out.println(chash);

(9)获取某个key下所有匹配的field-value代替key*

//当前ahash 数据为{d=4,e=5,c=3}
Cursor<Map.Entry<Object, Object>> cursor = redisTemplate.opsForHash().scan("ahash", ScanOptions.scanOptions().match("*").count(1000).build());
try {
    while (cursor.hasNext()) {
        Map.Entry<Object, Object> next = cursor.next();
        //key = d value = 4,key = e value = 5,key = c value = 3
        System.out.println("key = " +next.getKey() + " value = " + next.getValue());
    }
}catch (Exception e){
    e.printStackTrace();
}finally {
    //关闭cursor
    //游标一定要关闭,不然连接会一直增长;可以使用client lists`info clients`info stats命令查看客户端连接状态,会发现scan操作一直存在
    cursor.close();
}

4.Set

(1)单个/批量添加元素

//返回结果代表存入的个数
Long aset = redisTemplate.opsForSet().add("aset", "a");
System.out.println(aset);//1
Long aset2 = redisTemplate.opsForSet().add("aset", "a");
System.out.println(aset2);//0

List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
Long bset = redisTemplate.opsForSet().add("bset", list);
System.out.println(bset);//1 存储进去的是list对象 ["java.util.ArrayList",["a","b","c"]]
Long bset1 = redisTemplate.opsForSet().add("bset", list.toArray());
System.out.println(bset1);//3

(2)获取当前set中所有值

Set<Object> bset = redisTemplate.opsForSet().members("bset");
System.out.println(bset);//[c, a, b]

(3)获取当前set中元素个数

//当前bset中元素为 [c, a, b] cset不存在
Long bset = redisTemplate.opsForSet().size("bset");
System.out.println(bset);//3
Long cset = redisTemplate.opsForSet().size("cset");
System.out.println(cset);//0

(4)判断集合中是否包含某个value

//当前bset中元素为 [c, a, b] cset不存在
Boolean bset = redisTemplate.opsForSet().isMember("bset", "a");
System.out.println(bset);//true
Boolean cset = redisTemplate.opsForSet().isMember("cset", "a");
System.out.println(cset);//false

(5)从集合中随机获取N个元素(是/否去重)

//当前bset中元素为 [c, a, b, e] cset不存在
//随机获取集合中一个元素
Object bset = redisTemplate.opsForSet().randomMember("bset");
System.out.println(bset);//c
Object cset = redisTemplate.opsForSet().randomMember("cset");
System.out.println(cset);//null

//随机获取集合中N个元素
List<Object> randomSet = redisTemplate.opsForSet().randomMembers("bset",1);
System.out.println(randomSet);//[c]
List<Object> randomSets = redisTemplate.opsForSet().randomMembers("bset", 5);
System.out.println(randomSets);//[c, a, a, c, c] 这里注意如果set中元素数量<5 那么返回的集合是有重复的
List<Object> randomSetNull = redisTemplate.opsForSet().randomMembers("cset", 1);
System.out.println(randomSetNull);//[]

//对获取的数据进行去重
Set<Object> bset1 = redisTemplate.opsForSet().distinctRandomMembers("bset", 1);
System.out.println(bset1);//[c]
Set<Object> bset2 = redisTemplate.opsForSet().distinctRandomMembers("bset", 5);
System.out.println(bset2);//[a, c, e, b] 这里注意会进行去重
Set<Object> cset1 = redisTemplate.opsForSet().distinctRandomMembers("cset", 1);
System.out.println(cset1);//[]

(6)获取集合中所有的元素(遍历)

//当前bset中元素为 [c, a, b, e] cset不存在
Cursor<Object> cursor = redisTemplate.opsForSet().scan("cset", ScanOptions.scanOptions().match("*").count(1000).build());
System.out.println(cursor);//org.springframework.data.redis.core.ConvertingCursor@1ffc915
try {
    while (cursor.hasNext()) {
        Object next = cursor.next();
        //e c b a 注意 如果没有cset这个集合 此处不会进while
        System.out.println(next);
    }
}catch (Exception e){
    e.printStackTrace();
}finally {
    //关闭cursor
    //游标一定要关闭,不然连接会一直增长;可以使用client lists`info clients`info stats命令查看客户端连接状态,会发现scan操作一直存在
    cursor.close();
}

(7)单个/批量删除集合中的元素

//当前bset中元素为 [c, a, b, e] cset不存在
//返回值为成功删除的个数
Long removeCount = redisTemplate.opsForSet().remove("bset", "c");
System.out.println(removeCount);//1
Long removeCounts = redisTemplate.opsForSet().remove("bset", "a", "c");
System.out.println(removeCounts);//1
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
Long removeListCount = redisTemplate.opsForSet().remove("bset", list);
System.out.println(removeListCount);//0 这里删除为0 是把list当成一个整体了
Long removeSetNullCount = redisTemplate.opsForSet().remove("cset", "k");
System.out.println(removeSetNullCount);//0
Long remove = redisTemplate.opsForSet().remove("bset", list.toArray());
System.out.println(remove);//1

(8)删除并返回一个随机的元素

//当前bset中元素为 [e] cset不存在
//返回值为被删除的元素
Object bset = redisTemplate.opsForSet().pop("bset");
System.out.println(bset);//e
Object cset = redisTemplate.opsForSet().pop("cset");
System.out.println(cset);//null

(9)求两个/多个集合的交集

//当前aset = [a b c d] bset = [a b e f] cset = [a j k]
//获取两个集合的交集
Set<Object> twoIntersect = redisTemplate.opsForSet().intersect("aset", "bset");
System.out.println(twoIntersect);//[b, a]
List<String> list = new ArrayList<>();
list.add("bset");
list.add("cset");
//获取多个集合的交集
Set<Object> moreIntersect = redisTemplate.opsForSet().intersect("aset", list);
System.out.println(moreIntersect);//[a]

(10)将两个/N个集合的交集存入另一个集合中

//当前aset = [a b c d] bset = [a b e f] cset = [a j k]
//将集合aset和bset的交集存入cset中 返回值为最后合并的集合中的元素数量
Long cset = redisTemplate.opsForSet().intersectAndStore("aset", "bset", "cset");
System.out.println(cset);//2 这里反复存储结果也一直是2 不是0 要注意一下 此时cset = [a b] j和k被删掉

//将集合aset和集合bset、cset的交集存入dset中
Long dset = redisTemplate.opsForSet().intersectAndStore("aset", Arrays.asList("bset", "cset"), "dset");
System.out.println(dset);//2 此时dset = [a b]

(11)求两个/多个集合的并集

//当前aset = [a b c d] bset = [a b e f] cset = [a j k]
//获取集合aset和bset的并集
Set<Object> union = redisTemplate.opsForSet().union("aset", "bset");
System.out.println(union);//[e, d, c, a, b, f]

//获取集合aset、bset、cset的并集
Set<Object> unionMore = redisTemplate.opsForSet().union("aset", Arrays.asList("bset", "cset"));
System.out.println(unionMore);//[d, b, c, e, a, j, k, f]

(12)将两个/N个集合的并集存入另一个集合中

//当前aset = [a b c d] bset = [a b e f] cset = [a j k] dset不存在
//获取集合aset和bset的并集并存入cset中
Long unionAndStore = redisTemplate.opsForSet().unionAndStore("aset", "bset", "cset");
System.out.println(unionAndStore);//6 cset=[a b c d e f] 原cset中的j、k被删除掉

//获取集合aset、bset、cset的并集并存入dset中
Long unionAndStore1 = redisTemplate.opsForSet().unionAndStore("aset", Arrays.asList("bset", "cset"), "dset");
System.out.println(unionAndStore1);//6 dset=[a b c d e f]

//fset、kset、lset都不存在
Long unionAndStore2 = redisTemplate.opsForSet().unionAndStore("fset", "kset", "lset");
System.out.println(unionAndStore2);//0 也不是新建fset、kset、lset

(13)求两个集合的差集

//当前aset = [a b c d] bset = [a b e f] cset = [a j k] dset不存在
//获取集合aset和bset的差集
Set<Object> difference = redisTemplate.opsForSet().difference("aset", "bset");
System.out.println(difference);//[c, d] 这里要注意bset中的e f不在结果里
//获取集合aset、bset、cset的差集
Set<Object> differenceMore = redisTemplate.opsForSet().difference("aset", Arrays.asList("bset", "cset"));
System.out.println(differenceMore);//[d, c]

(14)将两个/N个集合的差集存入另一个集合中

//当前aset = [a b c d] bset = [a b e f] cset = [a j k] , dset、fset不存在
//获取集合aset和bset的差集并存入dset中
Long differenceAndStore = redisTemplate.opsForSet().differenceAndStore("aset", "bset", "dset");
System.out.println(differenceAndStore);//2 dset = [d c]

//获取集合aset、bset、cset的差集并存入fset中
Long differenceAndStoreMore = redisTemplate.opsForSet().differenceAndStore("aset", Arrays.asList("bset", "cset"),"fset");
System.out.println(differenceAndStoreMore);//2 fset = [d c]

//获取集合aset、bset的差集并存入cset中
Long differenceAndStoreMore1 = redisTemplate.opsForSet().differenceAndStore("aset", Arrays.asList("bset"),"cset");
System.out.println(differenceAndStoreMore1);//2 cset = [d c] 注意cset中的原值都被删除了

5.Zset

(1)添加元素

//1为score分数,有序集合是按照元素的score值由小到大进行排列
Boolean result = redisTemplate.opsForZSet().add("azset", "a", 1);
System.out.println(result);//true
Boolean result1 = redisTemplate.opsForZSet().add("azset", "a", 1);
System.out.println(result1);//false
Boolean result2 = redisTemplate.opsForZSet().add("azset", "a", 2);
System.out.println(result2);//false 注意: 这里虽然返回false 但是a的score值却被成功修改成了2
Boolean result3 = redisTemplate.opsForZSet().add("azset", "b", 2);
System.out.println(result3);//true
Boolean result4 = redisTemplate.opsForZSet().add("azset", "c", 1);
System.out.println(result4);//true
//此时azset集合中元素顺序为[c a b] 即如果评分一致的情况下 按照add的先后顺序排列

(2)增加/减少元素的score值,并返回增加/减少后的值

//初始azset集合中元素顺序为[c=1 a=2 b=2] 返回值是修改后的新分数
//将a评分+1
Double newScore1 = redisTemplate.opsForZSet().incrementScore("azset", "a", 1);
System.out.println(newScore1);//3.0 此时azset集合中元素顺序为[c=1 b=2 a=3]
//将a评分-1
Double newScore2 = redisTemplate.opsForZSet().incrementScore("azset", "a", -1);
System.out.println(newScore2);//2.0
//没有的元素就创建
Double newScore3 = redisTemplate.opsForZSet().incrementScore("azset", "d", 1);
System.out.println(newScore3);//1.0 此时azset集合中的元素顺序为[c=1 d=1 a=2 b=2] 
//没有的集合也会创建
Double newScore4 = redisTemplate.opsForZSet().incrementScore("bzset", "d", 1);
System.out.println(newScore4);//1.0 bzset集合会被创建[d=1]

(3)返回元素在集合中的排名

//初始azset集合中元素顺序为[a=1 b=2 c=2 d=3]
//按照score评分从小到大排列获取排名 索引从0开始算
Long aRank = redisTemplate.opsForZSet().rank("azset", "a");
System.out.println(aRank);//0
Long bRank = redisTemplate.opsForZSet().rank("azset", "b");
System.out.println(bRank);//1
Long cRank = redisTemplate.opsForZSet().rank("azset", "c");
System.out.println(cRank);//2
Long dRank = redisTemplate.opsForZSet().rank("azset", "d");
System.out.println(dRank);//3
Long eRank = redisTemplate.opsForZSet().rank("azset", "e");
System.out.println(eRank);//null

//reverseRank与rank正好相反 按照score评分从大到小排列获取排名 索引从0开始算
Long reverseRank = redisTemplate.opsForZSet().reverseRank("azset", "d");
System.out.println(reverseRank);//0

(4)获取集合的大小

//初始azset集合中元素顺序为[a=1 b=2 c=2 d=3] bzset不存在
//方法1
Long aSize = redisTemplate.opsForZSet().size("azset");
System.out.println(aSize);//4
Long bSize = redisTemplate.opsForZSet().size("bzset");
System.out.println(bSize);//0

//方法2
Long aZcard = redisTemplate.opsForZSet().zCard("azset");
System.out.println(aZcard);//4
Long bZcard = redisTemplate.opsForZSet().zCard("bzset");
System.out.println(bZcard);//0

(5)根据key-value查询对应的score值

//初始azset集合中元素顺序为[a=1 b=2 c=2 d=3] bzset不存在
Double score = redisTemplate.opsForZSet().score("azset", "a");
System.out.println(score);//1.0

Double score1 = redisTemplate.opsForZSet().score("bzset", "a");
System.out.println(score1);//null

(6)获取集合中给定区间的元素(按照分数从大到小顺序)

//语法 redisTemplate.opsForZSet().reverseRangeWithScores(key,start,end)
//初始azset集合中元素顺序为[a=1 b=2 c=2 d=3] bzset不存在
//这里是按照分数从大到小获取的
Set<ZSetOperations.TypedTuple<Object>> azset = redisTemplate.opsForZSet().reverseRangeWithScores("azset", 0, 1);
azset.stream().forEach(s->{
    //value = d score = 3.0
    //value = c score = 2.0 
    System.out.println("value = "+s.getValue() + " score = "+s.getScore());
});

//-1代表查询所有
Set<ZSetOperations.TypedTuple<Object>> allAzset = redisTemplate.opsForZSet().reverseRangeWithScores("azset", 0, -1);
allAzset.stream().forEach(s->{
    //value = d score = 3.0
    //value = c score = 2.0
    //value = b score = 2.0
    //value = a score = 1.0
    System.out.println("value = "+s.getValue() + " score = "+s.getScore());
});

Set<ZSetOperations.TypedTuple<Object>> nullAzset = redisTemplate.opsForZSet().reverseRangeWithScores("bzset", 0, 1);
nullAzset.stream().forEach(s->{
    //无
    System.out.println("value = "+s.getValue() + " score = "+s.getScore());
});

(7)按照Score值查询集合中的元素

//初始azset集合中元素顺序为[a=1 b=2 c=2 d=3] bzset不存在

//语法1: redisTemplate.opsForZSet().reverseRangeByScore(key, min, max)
Set<Object> azset = redisTemplate.opsForZSet().reverseRangeByScore("azset", 1, 2);
System.out.println(azset);//[c, b, a]

//语法2: redisTemplate.opsForZSet().reverseRangeByScoreWithScores(key, min, max)
Set<ZSetOperations.TypedTuple<Object>> azset1 = redisTemplate.opsForZSet().reverseRangeByScoreWithScores("azset", 1, 2);
azset1.stream().forEach(s->{
    //value = c score = 2.0
    //value = b score = 2.0
    //value = a score = 1.0
    System.out.println("value = "+s.getValue() + " score = "+s.getScore());
});

(8)根据score值获取集合元素数量

//初始azset集合中元素顺序为[a=1 b=2 c=2 d=3] bzset不存在
//语法: redisTemplate.opsForZSet().count(key, min, max)
Long azsetCount = redisTemplate.opsForZSet().count("azset", 1, 2);
System.out.println(azsetCount);//3

(9)从高到低的排序集中获取分数在最小和最大值之间的元素

//初始azset集合中元素顺序为[a=1 b=2 c=2 d=3] bzset不存在
//语法: redisTemplate.opsForZSet().reverseRangeByScore(key, min, max, start, end)
Set<Object> azset = redisTemplate.opsForZSet().reverseRangeByScore("azset", 1, 2, 1, 2);
System.out.println(azset);//[b, a]

(10)将两个/N个集合的交集/并集存入其他集合中

//初始azset=[a=1 b=2 c=2 d=3] bzset=[a=1 b=3] czset=[f=5] dzset、fzset不存在
//返回值为最后参数的集合对应的元素个数

//将azset和bzset取交集并将结果存入dzset 原dzset内容会被删除掉
Long count1 = redisTemplate.opsForZSet().intersectAndStore("azset", "bzset", "dzset");
System.out.println(count1);//2 此时dzset=[a=2,b=5]

//将azset和bzset和czset取交集并将结果存入dzset 原dzset内容会被删除掉
Long count2 = redisTemplate.opsForZSet().intersectAndStore("azset", Arrays.asList("bzset","czset"), "dzset");
System.out.println(count2);//0 此时因为azset、bzset、czset三个集合没有交集元素 所以dzset被删除掉或者说里面没有元素了 原元素被覆盖

//将azset和bzset取并集并将结果存入dzset 原dzset内容会被删除掉
Long count3 = redisTemplate.opsForZSet().unionAndStore("azset", "bzset", "dzset");
System.out.println(count3);//4 此时dzset=[a=2,c=2,d=3,b=5]

//将azset和bzset和czset取并集并将结果存入dzset 原dzset内容会被删除掉
Long count4 = redisTemplate.opsForZSet().unionAndStore("azset", Arrays.asList("bzset","czset"), "dzset");
System.out.println(count4);//5 此时dzset=[a=2,c=2,d=3,b=5,f=5]

(11)遍历集合中匹配/全部的元素

//初始azset=[a=1 b=2 c=2 d=3]

//ScanOptions.NONE代表取所有
Cursor<ZSetOperations.TypedTuple<Object>> cursor = redisTemplate.opsForZSet().scan("azset", ScanOptions.NONE);
//通过match匹配并取前1000条
//Cursor<ZSetOperations.TypedTuple<Object>> cursor1 = redisTemplate.opsForZSet().scan("azset", ScanOptions.scanOptions().match("*").count(1000).build());

try {
    while (cursor.hasNext()) {
        ZSetOperations.TypedTuple<Object> next = cursor.next();
        //score = 1.0 value = a
        //score = 2.0 value = b
        //score = 2.0 value = c
        //score = 3.0 value = d
        System.out.println("score = " + next.getScore() + " value = " + next.getValue());
    }
}catch (Exception e){
    e.printStackTrace();
}finally {
    //关闭cursor
    //游标一定要关闭,不然连接会一直增长;可以使用client lists`info clients`info stats命令查看客户端连接状态,会发现scan操作一直存在
    cursor.close();
}

(12)删除元素

//初始azset=[a=1 b=2 c=2 d=3 e=4 f=5 g=6 h=7]

//单个删除
Long remove1 = redisTemplate.opsForZSet().remove("azset", "a");
System.out.println(remove1);//1 此时azset=[b=2 c=2 d=3 e=4 f=5 g=6 h=7]
//批量删除
Long remove2 = redisTemplate.opsForZSet().remove("azset", Arrays.asList("b","c"));
System.out.println(remove2);//0 此时azset=[b=2 c=2 d=3 e=4 f=5 g=6 h=7] 没有变化 因为要删除的是一个list对象
//批量删除
Long remove3 = redisTemplate.opsForZSet().remove("azset", Arrays.asList("b","d").toArray());
System.out.println(remove3);//2 此时azset=[c=2 e=4 f=5 g=6 h=7]
//根据索引范围删除
Long remove4 = redisTemplate.opsForZSet().removeRange("azset", 1, 2);
System.out.println(remove4);//2 此时azset=[c=2 g=6 h=7] 删除的索引从0开始算 且按照score从小到大顺序删除的
//根据分数范围删除
Long remove5 = redisTemplate.opsForZSet().removeRangeByScore("azset", 5, 6);
System.out.println(remove5);//1 此时azset=[c=2 h=7]