文章目录

  • 概述
  • 常用集合命令
  • 交集、并集和差集保存命令的用法
  • Spring中操作Redis 集合命令
  • 注意
  • 代码

概述

Redis 的集合不是一个线性结构,而是一个哈希表结构,它的内部会根据 hash 分子来存储和查找数据,理论上一个集合可以存储2的32次方减一(约42亿)个元素。

因为采用哈希表结构,所以对于 Redis 集合的插入、删除和查找的复杂度都是 0(1),只是我们需要注意 3 点

  1. 对于集合而言,它的每一个元素都是不能重复的,当插入相同记录的时候都会失败
  2. 集合是无序的
  3. 集合的每一个元素都是 String 数据结构类型

常用集合命令

官网: https://redis.io/commands#set

Redis 的集合可以对于不同的集合进行操作,比如求出两个或者以上集合的交集、 差集和并集等

命令 说明 备注
sadd key member1 [member2 member3 …] 给键为 key 的集合增加成员 可以同时增加多个
scard key 统计键为 key 的集合成员数
sdiff key1 [key2] 找出两个综合的差集 参数如果是单 key,那么 Redis 就返回这个 key 的所有元素
sdiffstore des key1 [key2] 先按 sdiff命令的规则,找出 key1 和 key2 两个集合的差集,然后将其保存到 des 集合
sinter key1 [key2] 求 key1 和 key2 两个集合的交集。 参数如果是单 key,那么 Redis 就返回这个 key 的所有元素
sinterstore des key1 key2 先按 sinter 命令的规则,找出 key1和 kye2两个集合的交集,然后保存到 des 中
sismember key member 判断 member 是否键为 key 的集合的成员 如果是返回1 , 否则返回0
smembers key 返回集合所有成员 如果数据最大,需要考虑法代泡历的问题
smove src des member 将成员 member 从集合 src 迁移到集合 des 中
spop key 随机弹出集合的一个元素 注意其随机性 , 因为集合是无序的
srandmember key [count] 随机返回集合 中一个或者多个元素 , count为限制返回总数,如果 count 为负数 , 则先求其绝对值 count 为整数,如果不填默认为1,如果count 大于等于集合总数, 则返回整个集合
srem key member1 [ member2 …] 移除集合中 的元素,可以是多个元素 对于很大 的集合可以通过它删除部分元素,避免删除大量数据引发 Redis 停顿
sunion key1 [key2] 求两个集合的并集 参数如果是单 key,那么 Redis 就返回这个 key 的所有元索
sunionstore des key1 key2 先执行 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"><!--最大空闲数 --><property name="maxIdle" value="${redis.maxIdle}" /><!--连接池的最大数据库连接数 --><property name="maxTotal" value="${redis.maxTotal}" /><!--最大建立连接等待时间 --><property name="maxWaitMillis" value="${redis.maxWaitMillis}" /><!--逐出连接的最小空闲时间 默认1800000毫秒(30分钟) --><property name="minEvictableIdleTimeMillis" value="${redis.minEvictableIdleTimeMillis}" /><!--每次逐出检查时 逐出的最大数目 如果为负数就是 : 1/abs(n), 默认3 --><property name="numTestsPerEvictionRun" value="${redis.numTestsPerEvictionRun}" /><!--逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-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);}// 删除一个集合的元素,参数可以是多个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相关推荐

  1. redis的数据结构||1) 字符串类型2) 哈希类型3) 列表类型4) 集合类型 5) 有序集合类型详解

    2. 下载安装     1. 官网:https://redis.io     2. 中文网:http://www.redis.net.cn/     3. 解压直接可以使用:         * re ...

  2. Redis的数据结构及应用场景

    2019独角兽企业重金招聘Python工程师标准>>> 一. 谈谈对redis的理解,它的应用场景. Redis是一个key-value存储系统,它支持存储的value类型包括str ...

  3. Redis 中的集合类型是怎么实现的?

    本文是<Redis内部数据结构详解>系列的第七篇.在本文中,我们围绕一个Redis的内部数据结构--intset展开讨论. Redis里面使用intset是为了实现集合(set)这种对外的 ...

  4. 你真的懂redis的数据结构了吗?redis内部数据结构和外部数据结构揭秘

    Redis有哪些数据结构? 字符串String.字典Hash.列表List.集合Set.有序集合SortedSet. 很多人面试时都遇到过这种场景吧? 其实除了上面的几种常见数据结构,还需要加上数据结 ...

  5. 将一个键值对添加入一个对象_细品Redis高性能数据结构之hash对象

    背景 上一节讲Redis的高性能字符串结构SDS,今天我们来看一下redis的hash对象. Hash对象 简介 redis的hash对象有两种编码(底层实现)方式,字典编码和压缩列表编码.在使用字典 ...

  6. redis内部数据结构深入浅出

    最大感受,无论从设计还是源码,Redis都尽量做到简单,其中运用到的原理也通俗易懂.特别是源码,简洁易读,真正做到clean and clear, 这篇文章以unstable分支的源码为基准,先从大体 ...

  7. Redis之数据结构底层实现

    目录 redis底层数据结构实现 Redis数据结构 String字符串 常用命令 SDS的定义 SDS的好处 应用场景 List列表 常用命令 压缩列表ziplist quicklist 应用场景 ...

  8. Redis高级数据结构原理解析-bitmap,hyperloglog

    Redis 位图 开发过程中,我们可能遇到这种场景记录用户的打卡情况,签到情况,这些场景只有两种结果,有或者没有,加入记录的数据量比较大,比如用一年的数据,如果用Redis中普通key/value,每 ...

  9. Redis基础数据结构内部实现简单介绍

    5种基础数据结构 Redis有5种基础数据结构,分别是:String(字符串),list(列表),hash(字典),set(集合),zset(有序集合),这五种是我们开发种经常用的到的,是Redis种 ...

  10. 保存到redis的字符串类型出现斜杆_深入浅出Redis:这次从Redis底层数据结构开始...

    1.概述 相信使用过Redis 的各位同学都很清楚,Redis 是一个基于键值对(key-value)的分布式存储系统,与Memcached类似,却优于Memcached的一个高性能的key-valu ...

最新文章

  1. intval0.57100 php_php中0,'',null,false,true,FLASE,TREU,array()的相等恒等学习
  2. 在Java中将Double转换为Integer
  3. HttpConnectionUtil
  4. OpenCV hdr成像技术的实例(附完整代码)
  5. spring整合mybatis基于xml配置
  6. 离婚从来不是解决家庭危机的唯一办法
  7. 事务对性能影响_不是事务的事务!(分布式事务系列-完结篇)
  8. echarts隐藏之后的显示问题
  9. C#图片处理之:在图片上画直线
  10. 【深度学习】机器视觉开源代码集合
  11. 凸优化第四章凸优化问题 4.6 广义不等式约束
  12. list遍历_Python遍历list,使用range和enumerate的效率区别
  13. 阿里云短信验证码发送
  14. 房产中介管理系统搭建
  15. FW:nbsp;司马相如琴挑文君真相:劫色劫…
  16. LeetCode—5757. 矩阵中最大的三个菱形和(Get Biggest ...)[中等]—分析及代码(Java)
  17. 系统学习机器学习之特征工程(一)--维度归约
  18. Python二级考试试题汇总(史上最全)
  19. 超码、候选码、主码(主键)、主属性、非主属性、关系数据库中的依赖、关系数据库范式、反范式
  20. 1027: 伊顿公学进入名校人数第2题(2级)输入两个用空格分隔的整数m和n,分别表示某年的毕业生人数和该年度进入某名校的百分比。输出输出一个整数count,表示该年度进入该名校的学生人数

热门文章

  1. 深度linux腾讯视频,在UOS/Deepin 20/Ubuntu 18.04下安装腾讯视频Linux版的方法
  2. recyclervie刷新到底部_RecyclerView底部刷新实现详解
  3. 深度学习模型压缩方法(3)-----模型剪枝(Pruning)
  4. Linux下CMake简明教程(五)正规一点的组织结构
  5. CMAKE_CURRENT_BINARY_DIR
  6. 选哪扇门得奖金的算法
  7. NTU课程笔记 :CV6422(4) sampling process
  8. 文巾解题 167. 两数之和 II - 输入有序数组
  9. linux实战应用案例: 如何在 Linux 安装 MySQL 8 数据库?(图文详细教程)
  10. Linux从入门到精通系列之SHELL编程循环语句语法及实例详解(forwhileuntil)