Redis-06Redis数据结构--集合Set
生活随笔
收集整理的這篇文章主要介紹了
Redis-06Redis数据结构--集合Set
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
文章目錄
- 概述
- 常用集合命令
- 交集、并集和差集保存命令的用法
- Spring中操作Redis 集合命令
- 注意
- 代碼
概述
Redis 的集合不是一個線性結構,而是一個哈希表結構,它的內部會根據(jù) hash 分子來存儲和查找數(shù)據(jù),理論上一個集合可以存儲2的32次方減一(約42億)個元素。
因為采用哈希表結構,所以對于 Redis 集合的插入、刪除和查找的復雜度都是 0(1),只是我們需要注意 3 點
常用集合命令
官網: https://redis.io/commands#set
Redis 的集合可以對于不同的集合進行操作,比如求出兩個或者以上集合的交集、 差集和并集等
| sadd key member1 [member2 member3 …] | 給鍵為 key 的集合增加成員 | 可以同時增加多個 |
| scard key | 統(tǒng)計鍵為 key 的集合成員數(shù) | |
| sdiff key1 [key2] | 找出兩個綜合的差集 | 參數(shù)如果是單 key,那么 Redis 就返回這個 key 的所有元素 |
| sdiffstore des key1 [key2] | 先按 sdiff命令的規(guī)則,找出 key1 和 key2 兩個集合的差集,然后將其保存到 des 集合 | |
| sinter key1 [key2] | 求 key1 和 key2 兩個集合的交集。 | 參數(shù)如果是單 key,那么 Redis 就返回這個 key 的所有元素 |
| sinterstore des key1 key2 | 先按 sinter 命令的規(guī)則,找出 key1和 kye2兩個集合的交集,然后保存到 des 中 | |
| sismember key member | 判斷 member 是否鍵為 key 的集合的成員 | 如果是返回1 , 否則返回0 |
| smembers key | 返回集合所有成員 | 如果數(shù)據(jù)最大,需要考慮法代泡歷的問題 |
| smove src des member | 將成員 member 從集合 src 遷移到集合 des 中 | |
| spop key | 隨機彈出集合的一個元素 | 注意其隨機性 , 因為集合是無序的 |
| srandmember key [count] | 隨機返回集合 中一個或者多個元素 , count為限制返回總數(shù),如果 count 為負數(shù) , 則先求其絕對值 | count 為整數(shù),如果不填默認為1,如果count 大于等于集合總數(shù), 則返回整個集合 |
| srem key member1 [ member2 …] | 移除集合中 的元素,可以是多個元素 | 對于很大 的集合可以通過它刪除部分元素,避免刪除大量數(shù)據(jù)引發(fā) Redis 停頓 |
| sunion key1 [key2] | 求兩個集合的并集 | 參數(shù)如果是單 key,那么 Redis 就返回這個 key 的所有元索 |
| sunionstore des key1 key2 | 先執(zhí)行 sunion 命令求 出并集,然后保存到鍵為 des 的集合中 |
上述命令的前綴都包含 了 一個 s,用來表達這是集合的命令 , 集合是無序的 , 并且支持并集 、 交集和差集的運算。
下面通過命令行客戶端來演示這些命令
127.0.0.1:6379> FLUSHDB OK 127.0.0.1:6379> SADD set1 v1 v2 v3 v4 v5 v6 (integer) 6 127.0.0.1:6379> SADD set2 v0 v2 v4 v6 v8 (integer) 5 127.0.0.1:6379> SCARD set1 (integer) 6 127.0.0.1:6379> SDIFF set1 set2 1) "v5" 2) "v1" 3) "v3" 127.0.0.1:6379> SINTER set1 set2 1) "v4" 2) "v6" 3) "v2" 127.0.0.1:6379> SISMEMBER set2 v2 (integer) 1 127.0.0.1:6379> SISMEMBER set1 v2 (integer) 1 127.0.0.1:6379> SISMEMBER set v2 (integer) 0 127.0.0.1:6379> SMEMBERS set2 1) "v4" 2) "v8" 3) "v6" 4) "v0" 5) "v2" 127.0.0.1:6379> SPOP set1 "v5" 127.0.0.1:6379> SMEMBERS set1 1) "v4" 2) "v6" 3) "v1" 4) "v2" 5) "v3" 127.0.0.1:6379> SRANDMEMBER set1 2 1) "v4" 2) "v3" 127.0.0.1:6379> SREM set1 v1 (integer) 1 127.0.0.1:6379> SMEMBERS set1 1) "v4" 2) "v6" 3) "v2" 4) "v3" 127.0.0.1:6379> SUNION set1 set2 1) "v4" 2) "v8" 3) "v6" 4) "v0" 5) "v2" 6) "v3" 127.0.0.1:6379> SMEMBERS set1 1) "v4" 2) "v6" 3) "v2" 4) "v3" 127.0.0.1:6379> SMEMBERS set2 1) "v4" 2) "v8" 3) "v6" 4) "v0" 5) "v2" 127.0.0.1:6379>交集、并集和差集保存命令的用法
127.0.0.1:6379> FLUSHDB OK 127.0.0.1:6379> SADD set1 v1 v2 v3 v4 v5 v6 (integer) 6 127.0.0.1:6379> SADD set2 v2 v4 v6 v8 (integer) 4 127.0.0.1:6379> SDIFFSTORE diff_set set1 set2 (integer) 3 127.0.0.1:6379> SMEMBERS diff_set 1) "v5" 2) "v1" 3) "v3" 127.0.0.1:6379> SUNIONSTORE union_set set1 set2 (integer) 7 127.0.0.1:6379> SMEMBERS union_set 1) "v4" 2) "v8" 3) "v5" 4) "v1" 5) "v6" 6) "v3" 7) "v2" 127.0.0.1:6379> SINTERSTORE inter_set set1 set2 (integer) 3 127.0.0.1:6379> SMEMBERS inter_set 1) "v6" 2) "v2" 3) "v4" 127.0.0.1:6379>上述命令主要是求差集、并集和交集 , 并保存到新的集合中。
Spring中操作Redis 集合命令
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"xmlns:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><context:property-placeholder location="classpath:redis/redis.properties" /><!--2,注意新版本2.3以后,JedisPoolConfig的property name,不是maxActive而是maxTotal,而且沒有maxWait屬性,建議看一下Jedis源碼或百度。 --><!-- redis連接池配置 --><bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"><!--最大空閑數(shù) --><property name="maxIdle" value="${redis.maxIdle}" /><!--連接池的最大數(shù)據(jù)庫連接數(shù) --><property name="maxTotal" value="${redis.maxTotal}" /><!--最大建立連接等待時間 --><property name="maxWaitMillis" value="${redis.maxWaitMillis}" /><!--逐出連接的最小空閑時間 默認1800000毫秒(30分鐘) --><property name="minEvictableIdleTimeMillis" value="${redis.minEvictableIdleTimeMillis}" /><!--每次逐出檢查時 逐出的最大數(shù)目 如果為負數(shù)就是 : 1/abs(n), 默認3 --><property name="numTestsPerEvictionRun" value="${redis.numTestsPerEvictionRun}" /><!--逐出掃描的時間間隔(毫秒) 如果為負數(shù),則不運行逐出線程, 默認-1 --><property name="timeBetweenEvictionRunsMillis" value="${redis.timeBetweenEvictionRunsMillis}" /><property name="testOnBorrow" value="true"></property><property name="testOnReturn" value="true"></property><property name="testWhileIdle" value="true"></property></bean><!--redis連接工廠 --><bean id="jedisConnectionFactory"class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"destroy-method="destroy"><property name="poolConfig" ref="jedisPoolConfig"></property><!--IP地址 --><property name="hostName" value="${redis.host.ip}"></property><!--端口號 --><property name="port" value="${redis.port}"></property><!--如果Redis設置有密碼 --><property name="password" value="${redis.password}" /> <!--客戶端超時時間單位是毫秒 --><property name="timeout" value="${redis.timeout}"></property><property name="usePool" value="true" /><!--<property name="database" value="0" /> --></bean><!-- 鍵值序列化器設置為String 類型 --><bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/><!-- redis template definition --><bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"p:connection-factory-ref="jedisConnectionFactory"p:keySerializer-ref="stringRedisSerializer"p:defaultSerializer-ref="stringRedisSerializer"p:valueSerializer-ref="stringRedisSerializer"></bean></beans> package com.artisan.redis.baseStructure.set;import java.util.List; import java.util.Set;import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.data.redis.core.RedisTemplate;/*** * * @ClassName: SpringRedisSetDemo* * @Description: 記得將 RedisTemplate 值序列化器設置為 StringRedisSerializer 然后運行該代碼* * @author: Mr.Yang* * @date: 2018年9月26日 下午3:22:57*/ public class SpringRedisSetDemo {private static final String SET1 = "set1";private static final String SET2 = "set2";public static void main(String[] args) {ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:spring/spring-redis-set.xml");RedisTemplate<String, String> redisTemplate = (RedisTemplate<String, String>) ctx.getBean("redisTemplate");Set<String> set = null;// 127.0.0.1:6379> FLUSHDB// OK// 127.0.0.1:6379> SADD set1 v1 v2 v3 v4 v5 v6// (integer) 6// 127.0.0.1:6379> SADD set2 v0 v2 v4 v6 v8// (integer) 5// 將元素加入列表redisTemplate.boundSetOps(SET1).add("v1", "v2", "v3", "v4", "v5", "v6");redisTemplate.boundSetOps(SET2).add("v0", "v2", "v4", "v6", "v8");// 127.0.0.1:6379> SCARD set1// (integer) 6// 求集合長度System.out.println(SET1 + "的長度為:" + redisTemplate.opsForSet().size(SET1));System.out.println(SET2 + "的長度為:" + redisTemplate.opsForSet().size(SET2));// 127.0.0.1:6379> SDIFF set1 set2// 1) "v5"// 2) "v1"// 3) "v3"// 求差集set = redisTemplate.opsForSet().difference(SET1, SET2);scanSet(set);// 求并集set = redisTemplate.opsForSet().intersect(SET1, SET2);scanSet(set);// 判斷是否是集合中的元素boolean exist = redisTemplate.opsForSet().isMember(SET1, "v1");System.out.println(SET1 + "中存在v1:" + exist);// 獲取集合所有元素set = redisTemplate.opsForSet().members(SET1);scanSet(set);set = redisTemplate.opsForSet().members(SET2);scanSet(set);// 從集合中隨機彈出一個元素,集合中會刪除該元素String randomValue = redisTemplate.opsForSet().pop(SET2);System.out.println(SET2 + "中彈出的隨機元素為" + randomValue);System.out.println(SET2 + "的長度為:" + redisTemplate.opsForSet().size(SET2));// 隨機獲取一個集合的元素 ,該元素仍然在集合中randomValue = (String) redisTemplate.opsForSet().randomMember(SET1);System.out.println(randomValue);System.out.println(SET1 + "的長度為:" + redisTemplate.opsForSet().size(SET1));System.out.println("------------");// 隨機獲取集合中 的4 個元素List<String> list = redisTemplate.opsForSet().randomMembers(SET1, 4);for (String string : list) {System.out.println(string);}// 刪除一個集合的元素,參數(shù)可以是多個Long value = redisTemplate.opsForSet().remove(SET1, "v1", "v2");System.out.println(SET1 + "中刪除了" + value + "個元素");System.out.println(SET1 + "的長度為:" + redisTemplate.opsForSet().size(SET1));// 求兩個集合的并集set = redisTemplate.opsForSet().union(SET1, SET2);scanSet(set);// 求兩個集合的差集,并保存到集合 diff_set 中redisTemplate.opsForSet().differenceAndStore(SET1, SET2, "diff_set");scanSet(redisTemplate.opsForSet().members("diff_set"));// 求兩個集合的交集,并保存到集合 inter_set 中redisTemplate.opsForSet().intersectAndStore(SET1, SET2, "inter_set");scanSet(redisTemplate.opsForSet().members("inter_set"));// 求兩個集合的并集,并保存到集合 union_set 中redisTemplate.opsForSet().unionAndStore(SET1, SET2, "union_set");scanSet(redisTemplate.opsForSet().members("union_set"));}private static void scanSet(Set<String> set) {for (String value : set) {System.out.println(value);}System.out.println("----------------");}}輸出
INFO : org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@73a8dfcc: startup date [Wed Sep 26 16:18:55 CST 2018]; root of context hierarchy INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [spring/spring-redis-set.xml] set1的長度為:6 set2的長度為:5 v5 v1 v3 ---------------- v4 v6 v2 ---------------- set1中存在v1:true v4 v5 v1 v6 v2 v3 ---------------- v4 v8 v6 v2 v0 ---------------- set2中彈出的隨機元素為v4 set2的長度為:4 v3 set1的長度為:6 ------------ v1 v1 v4 v4 set1中刪除了2個元素 set1的長度為:4 v4 v5 v8 v6 v0 v3 v2 ---------------- v5 v3 v4 ---------------- v6 ---------------- v4 v5 v8 v6 v0 v3 v2 ----------------注意
使用 Spring 提供的 RedisTemplate 去展示多個命令可以學習到如何使用 RedisTemplate 操作 Redis 。 實際工作中并不是那么用的,因為每一 個操作會嘗試從連接池里獲取 一 個新的 Redis 連接,多個命令應該使用SessionCallback 接口進行操作 。
代碼
代碼托管到了 https://github.com/yangshangwei/redis_learn
總結
以上是生活随笔為你收集整理的Redis-06Redis数据结构--集合Set的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Redis-04Redis数据结构--哈
- 下一篇: Redis-07Redis数据结构--有