Spring Boot 2.1.3 data-redis 概述 与 操作 Redis 5 种数据类型

目录

RedisTemplate 概述 与 redis 配置

RedisTemplate 使用演示

字符串(String)

列表(List)

哈希(Hash)

集合(Set)

有序集合(sorted set)


RedisTemplate 概述 与 redis 配置

1、Redis 是一个缓存、消息代理和功能丰富的键值存储。Spring Boot 为 LettuceJedis 客户端库提供基本的自动配置,并为 Spring Data Redis 提供抽象。官网传送

2、spring-boot-starter-data-redis 启动器,整合了需要的依赖项,默认情况下,它使用 Lettuce 作为客户端。这个启动器同时处理传统应用程序和反应性应用程序(reactive applications)。

3、官方还提供了一个 spring-boot-starter-data-redis-reactive 启动器,用于与具有 reactive 支持的其他存储保持一致。

4、可以像注入任何其他 Spring Bean 一样注入一个自动配置的 RedisConnectionFactory、StringRedisTemplate 或普通的 RedisTemplate 实例。class StringRedisTemplate extends RedisTemplate<String, String>

5、默认情况下,Redis 实例尝试连接本地主机(localhost)端口为 6379 的 Redis 服务器,默认使用空密码,连接 0 号数据库:

REDIS (RedisProperties)

spring.redis.cluster.max-redirects= # Maximum number of redirects to follow when executing commands across the cluster.
spring.redis.cluster.nodes= # Comma-separated list of "host:port" pairs to bootstrap from.
spring.redis.database=0 # Database index used by the connection factory.
spring.redis.url= # Connection URL. Overrides host, port, and password. User is ignored. Example: redis://user:[email protected]:6379
spring.redis.host=localhost # Redis server host.
spring.redis.jedis.pool.max-active=8 # Maximum number of connections that can be allocated by the pool at a given time. Use a negative value for no limit.
spring.redis.jedis.pool.max-idle=8 # Maximum number of "idle" connections in the pool. Use a negative value to indicate an unlimited number of idle connections.
spring.redis.jedis.pool.max-wait=-1ms # Maximum amount of time a connection allocation should block before throwing an exception when the pool is exhausted. Use a negative value to block indefinitely.
spring.redis.jedis.pool.min-idle=0 # Target for the minimum number of idle connections to maintain in the pool. This setting only has an effect if it is positive.
spring.redis.lettuce.pool.max-active=8 # Maximum number of connections that can be allocated by the pool at a given time. Use a negative value for no limit.
spring.redis.lettuce.pool.max-idle=8 # Maximum number of "idle" connections in the pool. Use a negative value to indicate an unlimited number of idle connections.
spring.redis.lettuce.pool.max-wait=-1ms # Maximum amount of time a connection allocation should block before throwing an exception when the pool is exhausted. Use a negative value to block indefinitely.
spring.redis.lettuce.pool.min-idle=0 # Target for the minimum number of idle connections to maintain in the pool. This setting only has an effect if it is positive.
spring.redis.lettuce.shutdown-timeout=100ms # Shutdown timeout.
spring.redis.password= # Login password of the redis server.
spring.redis.port=6379 # Redis server port.
spring.redis.sentinel.master= # Name of the Redis server.
spring.redis.sentinel.nodes= # Comma-separated list of "host:port" pairs.
spring.redis.ssl=false # Whether to enable SSL support.
spring.redis.timeout= # Connection timeout.

6、可以实现 LettuceClientConfigurationBuilderCustomizer 接口,以实现更高级的定制。如果使用的是 Jedis 客户端,则实现 JedisClientConfigurationBuilderCustomizer 接口。

RedisTemplate 默认自己的序列化速度并不理想,实际生产中遇到一次需要将数据库查出来的一个 List 对象放到 Redis 中,当时数据量达到 20 万行,结果 put 的时间长达 6、7 秒,然后当使用 alibaba 的 fastjson 先将 List 对象序列化为字符串,然后在 put 到缓存,此时时间降到了 100 毫秒内,而 fastjson 序列化同样非常之快。取值时,同样将取出的字符串使用 fastjosn 反序列化成 List 即可。

RedisTemplate 使用演示

1、RedisTemplate 对 lettuce 与 Jedis 封装之后,使用更加简单,如同使用 JDBCTemplate 对 JDBC 进行了封装。封装之后不需要再关心打开与关闭连接等繁琐的操作,而且它提供性能更好的连接池等。

2、本文环境 Spring Boot 2.1.3 + Java JDK 1.8,pom.xml 文件中导入依赖,然后在需要地方直接注入 RedisTemplate 或者 StringRedisTemplate 使用即可:

<!--Spring Boot redis 启动器-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!--如果配置文件中配置了 redis 的连接池,则需要导入commons-pool2依赖 -->
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
    <version>2.7.0</version>
</dependency>

3、全局配置文件配置 Redis 如下,连接本地没有设置密码的 Redis 服务器:

#Redis 配置,以下除了 timeout 外全部为默认配置.
spring:
  redis:
    host: localhost
    port: 6379
    database: 0
    password:
    timeout: 10000
    lettuce:
      pool:
        max-active: 8
        max-idle: 8
        min-idle: 0
        max-wait: -1ms

3、Redis 支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合),RedisTemplate 分别提供了对应的 API 进行操作它们。

字符串(String)

org.springframework.data.redis.core.ValueOperations 处理 String 类型数据:

方法 描述
set(K key, V value) 存储到 redis。key 已经存在时,覆盖旧值,不存在时新增。key、value 不能为 null
set(K key, V value, long timeout, TimeUnit unit) 设置失效时间为指定时间。超过后 key 会被移除
set(K key, V value, Duration timeout) 设置超时时间,Duration 是 Jdk 8 的 API。超过指定时间后,key 被移除
set(K key, V value, long offset) 覆写(overwrite)给定 key 所储存的字符串值,从偏移量 offset 开始
get(Object key) 获取指定 key 的 value,key 不存在时,返回 null。key 不能 null
getAndSet(K key, V value) 获取 key 的旧值,并赋值新的 value。key 不能 null
get(K key, long start, long end) 获取指定 key 指定范围的字符串 [start,end],从索引 0 开始。key 不能 null
append(K key, String value) 将新的 value 追加到 key 的旧值尾部,key 不存在时,自动新建。key 不能为 null。
Long size(K key) 获取 key 的 value 的长度,key 不存在时,返回 0。key 不能为 null。
Boolean setIfAbsent(K key, V value) 如果 key 不存在,则新增,否则不改变原来的值。其余重载方法与 set 方法对应。key、value 不能为 null。
Boolean setIfPresent(K key, V value, Duration timeout) key 存在时,才修改它的值,否则不新增,与 setIfAbsent 相反。
Long increment(K key) 将存储为字符串值的整数值增加1,并返回结果。key 不存在时自动新增
Long increment(K key, long delta) 将存储为字符串值的整数值增加 delta,并返回结果。key 不存在时自动新增。delta 为负数时,做减法
Double increment(K key, double delta) 将存储为字符串值的小数值增加 delta,并返回结果。key 不存在时自动新增
Long decrement(K key) 将存储为字符串的整数值减1,key 不存在时自动创建
Long decrement(K key, long delta) 减去指定的数值,key 不存在时自动创建。delta
List multiGet(Collection keys) 同时获取多个 key 的值,按请求的 key 的顺序返回对应的 value,key 不存在的返回 null。
multiSet(Map<? extends K, ? extends V> map) 同时存储多个 key-value
Boolean multiSetIfAbsent(Map<? extends K, ? extends V> map) 当 key 不存在时新增,否则进行操作。

https://github.com/spring-projects/spring-data-redis/blob/master/src/main/java/org/springframework/data/redis/core/ValueOperations.java

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.*;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.TimeUnit;

@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisStuWebApplicationTests {

    //注入 RedisTemplate 或者 StringRedisTemplate 其中一个即可,前者是后者的父类,它们都已经默认在 Spring 容器中了。
    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    //org.springframework.data.redis.core.ValueOperations 处理 String 类型数据
    @Test
    public void test1() {
        redisTemplate.getConnectionFactory().getConnection().flushAll();//清空 redis 所有缓存的数据。
        ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
        valueOperations.set("user.name", "张无忌 ");//添加值
        valueOperations.set("upload.process", "65", 60, TimeUnit.SECONDS);//添加值,失效时间60秒
        valueOperations.set("user.status", "online", Duration.ofSeconds(20));//添加值,失效时间20秒

        String user_name = valueOperations.get("user.name");//取值
        String upload_process = valueOperations.get("upload.process");//取值
        String user_status = valueOperations.get("user.status");//取值
        String user_status2 = valueOperations.get("user.status", 2, 4);//取值,截取子符串
        //输出:张无忌 , 65, online, lin
        System.out.println(user_name + ", " + upload_process + ", " + user_status + ", " + user_status2);

        Integer hello = valueOperations.append("user.hit", "Hello");//为末尾追加值
        String hit1 = valueOperations.get("user.hit");//取值
        Integer hello2 = valueOperations.append("user.hit", " World");//为末尾追加值
        String hit2 = valueOperations.get("user.hit");//取值
        Long size = valueOperations.size("user.hit");//字符串的长度
        //输出:5 - Hello, 11 - Hello World
        System.out.println(hello + " - " + hit1 + ", " + hello2 + " - " + hit2 + ", " + size);

        //key 不存在时,才进行添加
        Boolean aBoolean1 = valueOperations.setIfAbsent("name", "三丰", 60, TimeUnit.SECONDS);
        Boolean aBoolean2 = valueOperations.setIfAbsent("name", "四喜", 60, TimeUnit.SECONDS);
        System.out.println(aBoolean1 + ", " + aBoolean2 + ", " + valueOperations.get("name"));//输出:true, false, 三丰

        //key 存在时,才进行添加
        Boolean age1 = valueOperations.setIfPresent("age", "45", Duration.ofSeconds(60));
        valueOperations.set("age", "35");
        Boolean age2 = valueOperations.setIfPresent("age", "55", Duration.ofSeconds(60));
        System.out.println(age1 + ", " + age2 + ", " + valueOperations.get("age"));//输出:false, true, 55

        valueOperations.set("l1", "1", Duration.ofSeconds(60));
        valueOperations.set("d1", "3.14", Duration.ofSeconds(60));
        valueOperations.set("total", "100", Duration.ofSeconds(60));
        Long count1 = valueOperations.increment("l1");//数值做加法
        Long count2 = valueOperations.increment("l1", 10L);
        Double d1 = valueOperations.increment("d1", 40.00);
        Long total1 = valueOperations.decrement("total");//数值做减法
        Long total2 = valueOperations.decrement("total2", 35);
        System.out.println(count1 + ", " + count2 + ", " + d1 + ", " + total1 + ", " + total2);//输出:2, 12, 43.14, 99, 64

        List<String> keyList = new ArrayList<>();
        keyList.add("l1");
        keyList.add("d1");
        keyList.add("f1");
        List<String> list = valueOperations.multiGet(keyList);//同时获取多个 key 的 value
        System.out.println(list);//[12, 43.140000000000001, null]

        Map<String, String> dataMap = new LinkedHashMap<>();
        dataMap.put("multi_name", "雄霸");
        dataMap.put("multi_age", "44");
        valueOperations.multiSet(dataMap);//同时设置多个key-value
        //输出:[雄霸, 44]
        System.out.println(valueOperations.multiGet(Arrays.asList(new String[]{"multi_name", "multi_age"})));
    }
}

列表(List)

org.springframework.data.redis.core.ListOperations 处理 List 类型数据:

方法 描述
Long size(K key) 返回存储在键中的列表的长度。键不存在时,返回 0;key 存储的值不是列表时返回错误。
Long leftPush(K key, V value 将指定的值插入到列表的头部。键不存在自动创建。(从左边插入)。返回 list 的大小(size)。
Long leftPushAll(K key, V... values) 批量从左插入。key 不能为 null。返回 list 的大小(size)。
Long leftPushAll(K key, Collection values) 批量从左插入。key,values 不能为 null。
Long leftPush(K key, V pivot, V value) 对于名字为 key 的 list,从左往右先查询第一个出现的 pivot 元素,然后将 value 插入到它的左边。
Long leftPushIfPresent(K key, V value) 只有当 key 存在时,才新增,否则不处理。
Long rightPush(K key, V value) 右侧插入,key 不存在时,自动创建
Long rightPush(K key, V pivot, V value) 从左往右查找第一个 pivot 元素,然后将新的 value 插入到它的右侧。
Long rightPushAll(K key, Collection values) 右侧批量插入
Long rightPushAll(K key, V... values) 右侧批量插入
Long rightPushIfPresent(K key, V value) 当 key 存在时,进行右侧插入,否则不处理。
set(K key, long index, V value) 为名字为 key 的列表索引为 index 的元素替换为新的 value 值。key 必须存在,index 索引不能越界
Long remove(K key, long count, Object value) 删除列表(key) 中指定个数(count)的元素(value)。count=0:删除所有 value;count>0:从左往右删除 count 个 value;count<0,从右往左删除。
List range(K key, long start, long end) 查询 list 的元素值,索引范围为 [start,end],-1 表示倒数第一个元素
V index(K key, long index) 获取列表中指定索引处的元素。index 越界时,返回 null;key 不存在时,返回 null。索引 index=-1 表示倒数第一个元素。
V leftPop(K key) 弹出最左边的元素,弹出之后该值在列表中将不复存在。当列表为空时,返回 null。
V rightPop(K key) 弹出最右边的元素,弹出之后该值在列表中将不复存在。当列表为空时,返回 null。
V leftPop(K key, long timeout, TimeUnit unit) 弹出最左边的元素,当元素不存在时,线程阻塞等待,直到存在新元素,或者超时抛出异常
V rightPop(K key, long timeout, TimeUnit unit) 弹出最右边的元素,当元素不存在时,线程阻塞等待,直到存在新元素,或者超时抛出异常

https://github.com/spring-projects/spring-data-redis/blob/master/src/main/java/org/springframework/data/redis/core/ListOperations.java

    //org.springframework.data.redis.core.ListOperations 处理 List 类型数据
    @Test
    public void test2() {
        redisTemplate.getConnectionFactory().getConnection().flushAll();//清空 redis 所有缓存的数据。
        ListOperations<String, String> opsForList = stringRedisTemplate.opsForList();
        Long aLong1 = opsForList.leftPush("list_1", "USA");//将值添加到 list 头部
        Long aLong2 = opsForList.leftPush("list_1", "China");//将值添加到 list 头部
        Long aLong3 = opsForList.leftPushAll("list_1", new String[]{"Java", "C++", "USA", "WPF"});//将多个值添加到 list 头部
        Long size = opsForList.size("list_1");//获取 list 大小
        Long aLong4 = opsForList.leftPush("list_1", "Java", "C#");//将值添加到 list 头部
        Long aLong5 = opsForList.rightPush("list_1", "USA", "Tomcat");//将值添加到 list 头部
        //输出:1, 2, 6, 7, 8, 6
        System.out.println(aLong1 + ", " + aLong2 + ", " + aLong3 + ", " + aLong4 + ", " + aLong5 + ", " + size);
        System.out.println(opsForList.range("list_1", 0, -1));//输出:[WPF, USA, Tomcat, C++, C#, Java, China, USA]

        Long aLong = opsForList.leftPushIfPresent("list_2", "Apple");//当 key 存在时,才进行添加
        System.out.println(aLong + ", " + aLong5);//0, 8

        opsForList.rightPush("list_2", "2019");//将值添加到 list 尾部
        opsForList.rightPush("list_2", "2018");
        opsForList.rightPush("list_2", "2017");
        opsForList.set("list_2", 1, "2008");
        System.out.println(opsForList.range("list_2", 0, -1));//获取指定索引范围的值,[2019, 2008, 2017]

        //同时将多个值添加到右侧
        opsForList.rightPushAll("list_3", new String[]{"mysql", "oracle", "sql server", "redis", "oracle", "sql server", "redis", "oracle"});
        System.out.println(opsForList.range("list_3", 0, -1));//输出:[mysql, oracle, sql server, redis, oracle, sql server, redis, oracle]
        //删除 list 中所有的 "sql server" 值
        Long remove1 = opsForList.remove("list_3", 0, "sql server");//2 - [mysql, oracle, redis, oracle, redis, oracle]
        System.out.println(remove1 + " - " + opsForList.range("list_3", 0, -1));
        //从右往左删除第一次出现的 redis 值
        Long remove2 = opsForList.remove("list_3", -1, "redis");//1 - [mysql, oracle, redis, oracle, oracle]
        System.out.println(remove2 + " - " + opsForList.range("list_3", 0, -1));
        //从左往右删除第一次、第二次出现的 oracle 值
        Long remove3 = opsForList.remove("list_3", 2, "oracle");//2 - [mysql, redis, oracle]
        System.out.println(remove3 + " - " + opsForList.range("list_3", 0, -1));

        opsForList.rightPushAll("list_4", new String[]{"mysql", "oracle", "redis", "DB2"});
        String index1 = opsForList.index("list_4", -1);//查询倒数第一个元素
        String leftPop1 = opsForList.leftPop("list_4");//弹出头部第一个元素
        String rightPop1 = opsForList.rightPop("list_4");//弹出尾部第一个元素
        System.out.println(index1 + ", " + leftPop1 + ", " + rightPop1);//DB2, mysql, DB2

        opsForList.rightPushAll("list_5", new String[]{"Python", "C#", "Java"});
        for (int i = 0; i < 4; i++) {
            //弹出头部元素,当超过60秒还没有元素时,抛出异常 RedisCommandTimeoutException
            //System.out.println(opsForList.leftPop("list_5", 60, TimeUnit.SECONDS));//可以手动通过 redis 客户添加元素:lpush list_5 wmx
        }
    }

哈希(Hash)

org.springframework.data.redis.core.HashOperations 处理 Hash 类型数据:

方法 描述
Long size(H key) 获取指定 hash(key) 的元素个数,kye 不存在时,返回 0
Boolean hasKey(H key, Object hashKey) 判断 hash 中 是否存在指定的元素,key 不存在时,返回 false
Set keys(H key) 获取指定 hash(key) 中所有的 hashKey。key 不存在时,返回空集合[].
List values(H key) 获取指定 hash(key) 的所有值。key 不存在时,返回空 list
Long delete(H key, Object... hashKeys) 删除指定的 hash(key) 中指定的元素(hansKeys),返回成功删除元素个数,key 不存在时返回 0
void put(H key, HK hashKey, HV value) 往 key 中插入键值对 hashKey-value。hashKey 重复时,后插入的覆盖旧值。key 不存在时,自动新增
void putAll(H key, Map<? extends HK, ? extends HV> m) 单次插入多个元素。key 不存在时自动新增
Boolean putIfAbsent(H key, HK hashKey, HV value) key 或者 hashKey 不存在时,才插入值
HV get(H key, Object hashKey) 获取 hash 中指定的 hashKey,key 不存在时,返回 null.
Map<HK, HV> entries(H key) 获取指定 key 的 hash map。key 不存在时,返回空 map。
Long lengthOfValue(H key, HK hashKey) 获取 key 对应的 hash map 的 hashKey 对应的元素值的长度
List multiGet(H key, Collection hashKeys) 同时获取 key 对应的 hash map 中的多个元素值,hashKey 不存在时,返回 null
Long increment(H key, HK hashKey, long delta) 为指定 key 的 hash map 中的元素 hashKey 的数值加上整数值 delta。key 不存在时,直接新增。
Double increment(H key, HK hashKey, double delta) 为指定 key 的 hash map 中的元素 hashKey 的数值加上浮点数值 delta。key 不存在时,直接新增

https://github.com/spring-projects/spring-data-redis/blob/master/src/main/java/org/springframework/data/redis/core/HashOperations.java

    //org.springframework.data.redis.core.HashOperations 处理 hash 数据类型
    @Test
    public void test3() {
        redisTemplate.getConnectionFactory().getConnection().flushAll();//清空 redis 所有缓存的数据。

        HashOperations<String, Object, Object> opsForHash = stringRedisTemplate.opsForHash();
        Long delete = opsForHash.delete("hash_1", "name", "age");//删除指定元素
        Boolean hasKey = opsForHash.hasKey("hash_1", "name");//判断是否含有指定的元素
        Object name1 = opsForHash.get("hash_1", "name");//获取指定的元素
        Set<Object> keys = opsForHash.keys("hash_1");//获取所有的 key
        Long hash_1 = opsForHash.size("hash_1");//获取 hash 的大小
        System.out.println(delete + ", " + hasKey + ", " + name1 + ", " + keys + ", " + hash_1);//输出:0, false, null, [], 0

        Map<String, String> dataMap = new HashMap<>();
        dataMap.put("age", "33");
        dataMap.put("name", "Li Si");
        dataMap.put("address", "人民东路45号");
        opsForHash.put("hash_1", "name", "Zan San");//为 hash 添加单个元素
        opsForHash.putAll("hash_1", dataMap);//为 hash 添加多个元素
        opsForHash.putIfAbsent("hash_2", "name", "Chang Sha");//当 key 或者 hashKey 不存在时,才插入值

        List<Object> list = opsForHash.values("hash_1");//获取所有的 values
        Map<Object, Object> entries = opsForHash.entries("hash_1");//获取整个 hash
        Long lengthOfValue1 = opsForHash.lengthOfValue("hash_1", "name");//获取元素的长度
        Long lengthOfValue2 = opsForHash.lengthOfValue("hash_1", "age");
        List<Object> multiGet = opsForHash.multiGet("hash_1", Arrays.asList(new String[]{"name", "address", "birthday"}));//同时获取多个元素值

        //[Li Si, 人民东路45号, 33], {name=Li Si, address=人民东路45号, age=33}, 5, 2, [Li Si, 人民东路45号, null]
        System.out.println(list + ", " + entries + ", " + lengthOfValue1 + ", " + lengthOfValue2 + ", " + multiGet);

        Long increment_age1 = opsForHash.increment("hash_1", "age", 20);//数值元素做加法
        Double increment_age2 = opsForHash.increment("hash_1", "age", 20.45D);
        System.out.println(increment_age1 + ", " + increment_age2);//53, 73.45
    }

集合(Set)

org.springframework.data.redis.core.SetOperations 处理无序集合(Set) 类型数据:

方法 描述
Long add(K key, V... values) 往 set 中添加元素,key 不存在时,自动新建。value 重复时,覆盖旧值。返回 set 中的元素个数
Long remove(K key, Object... values) 移除 set 中的元素。返回 set 中剩余的元素个数.
Boolean move(K key, V value, K destKey) 将 key 对应的 set 中的值 value 剪切到目标 set(destKey) 中。key、value、destKey 不存在时,不做任何操作.
V pop(K key) 随机弹出 set 中的一个元素,弹出后,set 中就没有了。当 set 为空时,返回 null.
List pop(K key, long count) 随机弹出 set 中 count 个元素,如果 set 的大小为 3,而 count 为 5,此时只会返回 3 个元素。
Long size(K key) 获取 key 对应 set 的集合大小. key 不存在时,返回 0
Set members(K key) 获取 set 中所有的元素,key 不存在时,返回空 set.
V randomMember(K key) 从 set 中随机返回一个元素,set 中此元素还会存在。key 不存在时,返回 null.
List randomMembers(K key, long count) 随机返回 set 中 count 个元素。
Boolean isMember(K key, Object o) 判断 key 对应的 set 中是否包含元素 o。key 不存在时,返回 false。
Set union(K key, K otherKey) 获取 key 与 otherKey 对应的 set 的并集。旧值不受影响,返回合并后的值。
Set union(K key, Collection otherKeys) 获取多个 set 的并集
Long unionAndStore(K key, K otherKey, K destKey) 求 key 、otherKey 的 set 并集,并将结果添加到 destKey 中。destKey 不存在时,自动创建。返回新集合中的元素个数。当 destKey 中事先已经有值,则会被先清除。
Long unionAndStore(K key, Collection otherKeys, K destKey) 将多个 set 的并集结果放入到 destKey 对应的 set 中,destKey 不存在时,自动创建。当 destKey 中事先已经有值,则会被先清除。
Set difference(K key, K otherKey) 求 key 与 otherKey 对应的 set 的差集,key 减去 otherKey 后剩余的结果。
Set difference(K key, Collection otherKeys) 获取 key 与所有 otherKeys 的差集。
Long differenceAndStore(K key, K otherKey, K destKey) 将差集结果放入到 destKey 中。当 destKey 中事先已经有值,则会被先清除。
Long differenceAndStore(K key, Collection otherKeys, K destKey) 将差集结果放入到 destKey 中。当 destKey 中事先已经有值,则会被先清除。
Set intersect(K key, K otherKey) 获取 key 与 otherKey 的交集,双方都拥有的元素
Set intersect(K key, Collection otherKeys) 获取 key 与其它所有 otherKeys 的交集
Long intersectAndStore(K key, K otherKey, K destKey) 将交集结果放到 destKey 集合中。当 destKey 中事先已经有值,则会被先清除。
Long intersectAndStore(K key, Collection otherKeys, K destKey) 将交集结果放到 destKey 集合中。当 destKey 中事先已经有值,则会被先清除。

https://github.com/spring-projects/spring-data-redis/blob/master/src/main/java/org/springframework/data/redis/core/SetOperations.java

//org.springframework.data.redis.core.SetOperations 处理 Set 类型数据:
    @Test
    public void test4() {
        stringRedisTemplate.getConnectionFactory().getConnection().flushAll();//情况所有缓存数据
        SetOperations<String, String> opsForSet = stringRedisTemplate.opsForSet();
        Long add = opsForSet.add("set_1", "C", "Java", "Python");//往集合添加元素
        Long remove = opsForSet.remove("set_1", "C");//删除元素
        String set_1 = opsForSet.pop("set_1");//随机弹出 set 中的一个元素
        System.out.println(add + ", " + remove + ", " + set_1);//3, 1, Python

        opsForSet.add("set_2", "华山", "泰山", "衡山");
        Set<String> set_2 = opsForSet.members("set_2");//查询 set 中的所有元素
        opsForSet.move("set_1", "Java", "set_2");
        System.out.println(set_2);//[泰山, 衡山, 华山]
        Long size = opsForSet.size("set_2");//获取 set 的大小
        System.out.println(opsForSet.members("set_2") + ", " + size);//[泰山, 衡山, 华山], 3

        Boolean member1 = opsForSet.isMember("set_2", "泰山");//判断 set 中是否含义指定的元素值
        Boolean member2 = opsForSet.isMember("set_2", "嵩山");
        System.out.println(member1 + ", " + member2);//true, false

        opsForSet.add("set_3", "Oracle", "Mysql", "DB2", "H2", "Sql Server");
        List<String> set_3 = opsForSet.pop("set_3", 3);
        System.out.println(set_3);//[Oracle, DB2, Mysql]

        opsForSet.add("set_4", "段誉", "乔峰", "虚竹", "王语嫣", "慕容复");
        System.out.println(opsForSet.members("set_4") + ", " + opsForSet.randomMember("set_41"));
        System.out.println(opsForSet.randomMembers("set_4", 3));//随机弹出 set 中指定个数的元素,如随机弹出其中3个元素

        opsForSet.add("set_5_1", "a", "b", "c", "1", "2", "3");
        opsForSet.add("set_5_2", "x", "y", "c", "21", "2", "3");
        Set<String> union1 = opsForSet.union("set_5_1", "set_5_2");//两个集合求并集
        System.out.println(opsForSet.members("set_5_1") + ", " + opsForSet.members("set_5_2"));
        System.out.println(union1);//[3, a, x, c, b, 2, 21, 1, y]

        //多个集合求并集
        Set<String> set_5_1 = opsForSet.union("set_5_1", Arrays.asList(new String[]{"set_5_2", "set_4"}));
        System.out.println(set_5_1);//[王语嫣, 段誉, 21, a, 3, 虚竹, x, b, c, 慕容复, 1, y, 乔峰, 2]

        //多个集合求并集,并将结果存储到新的集合中
        Long aLong = opsForSet.unionAndStore("set_5_1", "set_5_2", "set_5_3");
        System.out.println(aLong + ", " + opsForSet.members("set_5_3"));//9, [3, a, x, c, b, 2, 21, 1, y]

        Set<String> difference = opsForSet.difference("set_5_1", "set_5_2");//求两个集合的差集
        System.out.println(difference);//[a, 1, b]

        Set<String> intersect = opsForSet.intersect("set_5_1", "set_5_2");//求两个集合的交集
        opsForSet.intersectAndStore("set_5_1", "set_5_2", "set_5_3");//当set_5_3集合中有值时,会先被清除
        System.out.println(intersect);//[3, c, 2]
    }

有序集合(sorted set)

org.springframework.data.redis.core.ZSetOperations 处理有序集合(Set) 的数据:

方法 描述
Boolean add(K key, V value, double score) 为有序集合添加元素. 如果 value 已经存在,则更新. score 表示权重,用于排序,值越小,排序越靠前(由小到大)。key 不存在时,直接新增。成功插入时返回 true,失败时返回 false。
Long rank(K key, Object o) 获取元素 o 在有序集合中的索引
Set range(K key, long start, long end) 获取有序的集合中指定索引范围的值,索引从0开始,-1 表示倒数第一个元素。
Set rangeByScore(K key, double min, double max) 根据权重范围查询
Set rangeByScore(K key, double min, double max, long offset, long count) offset 表示偏移量,count 表示需要获取的个数
Long count(K key, double min, double max) 获取权重在 [min,max] 直接的元素个数
Long remove(K key, Object... values) 删除有序集合中指定的元素(value)
Long removeRange(K key, long start, long end) 删除有序集合中指定索引范围内的元素
Long removeRangeByScore(K key, double min, double max) 删除有序集合中指定权重范围内的元素
Long zCard(K key) 获取集合的大小
Long size(K key) 获取集合的大小,底层调用 zCard
Double score(K key, Object o) 获取集合中指定元素的权重。

https://github.com/spring-projects/spring-data-redis/blob/master/src/main/java/org/springframework/data/redis/core/ZSetOperations.java


    //org.springframework.data.redis.core.ZSetOperations 处理有序集合(Set) 的数据:
    @Test
    public void test5() {
        stringRedisTemplate.getConnectionFactory().getConnection().flushAll();//清空所有缓存
        ZSetOperations<String, String> opsForZSet = stringRedisTemplate.opsForZSet();
        Boolean add1 = opsForZSet.add("zset1", "C++", 3.8);
        Boolean add2 = opsForZSet.add("zset1", "Java", 0.3);
        Boolean add3 = opsForZSet.add("zset1", "Python", 2.5);
        Set<String> zset1 = opsForZSet.range("zset1", 0, -1);
        System.out.println(add1 + ", " + add2 + ", " + add3 + ", " + zset1);//输出:true, true, true, [Java, Python, C++]

        Long rank = opsForZSet.rank("zset1", "C++");
        Long count = opsForZSet.count("zset1", 0.3, 2.5);
        Long size = opsForZSet.size("zset1");
        Double score = opsForZSet.score("zset1", "Java");
        //输出:2, 2, 3, 0.3, [Java, Python, C++]
        System.out.println(rank + ", " + count + ", " + size + ", " + score + ", " +
                opsForZSet.range("zset1", 0, -1));

        opsForZSet.add("zset2", "12", 0);
        opsForZSet.add("zset2", "3c", 1);
        opsForZSet.add("zset2", "4f", 2);
        opsForZSet.add("zset2", "6h", 3);
        opsForZSet.add("zset2", "7p", 4);
        Long remove = opsForZSet.remove("zset2", "4f");
        //Long aLong = opsForZSet.removeRange("zset2", 1, 2);
        Long zset2 = opsForZSet.removeRangeByScore("zset2", 2.0, 3.0);
        System.out.println(opsForZSet.range("zset2", 0, -1));
    }
发布了458 篇原创文章 · 获赞 884 · 访问量 92万+

猜你喜欢

转载自blog.csdn.net/wangmx1993328/article/details/103253479