Spring Boot 2.1.3 RedisTemplate 概述 與 操作 Redis 5 種數據類型

目錄

RedisTemplate 概述

RedisTemplate 使用

字符串(String)

列表(List)

哈希(Hash)

集合(Set)

有序集合(sorted set)


RedisTemplate 概述

1、Redis 是一個緩存、消息代理和功能豐富的鍵值存儲。Spring Boot 爲 Lettuce Jedis 客戶端庫提供基本的自動配置,併爲 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 即可。

7、Redis 三個客戶端框架:Jedis、Redisson、Lettuce 對比。

RedisTemplate 使用

RedisAutoConfiguration 中已經自動將 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 容器中了。
    //org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration 中已經自動將 RedisTemplate 添加到了容器中,直接獲取使用即可.
    @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));
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章