Redis Set集合命令、内部编码及应用场景(详细)

文章目录

前言

集合类型也是保存多个字符串类型的元素的,但和列表类型不同的是,集合中
1)元素之间是无序
2)元素不允许重复,如下图所示。一个集合中最多可以存储 2 32 − 1 2^{32} - 1 232−1 个元素。
Redis除了支持集合内的增删查改操作,同时还支持多个集合取 交集并集差集

集合类型


普通命令

SADD

SADD key member [member ...]

将一个或者多个元素添加到 set 中。注意,重复的元素 无法添加 到set中。
时间复杂度:O(1)
返回值:本次添加成功的元素个数。

java 复制代码
 redis> SADD myset "Hello"
 (integer) 1
 redis> SADD myset "World"
 (integer) 1
 redis> SADD myset "World"
 (integer) 0
 redis> SMEMBERS myset
 1) "Hello"
 2) "World"

SMEMBERS

SMEMBERS key

获取一个set中的 所有元素,注意,元素间的顺序是 无序 的。
时间复杂度:O(N)
返回值:所有元素的列表。

java 复制代码
 redis> SADD myset "Hello"
 (integer) 1
 redis> SADD myset "World"
 (integer) 1
 redis> SMEMBERS myset
 1) "Hello"
 2) "World"

SISMEMBER

SISMEMBER key member

判断一个元素在不在set中
时间复杂度:O(1)
返回值:1 表示元素在set中。0 表示元素不在 set 中或者 key 不存在。

java 复制代码
 redis> SADD myset "one"
 (integer) 1
 redis> SISMEMBER myset "one"
 (integer) 1
 redis> SISMEMBER myset "two"
 (integer) 0

SCARD

SCARD key

获取一个set的基数(cardinality),即set中的 元素个数
时间复杂度:O(1)
返回值:set内的 元素个数

java 复制代码
redis> SADD myset "Hello"
(integer) 1
redis> SADD myset "World"
(integer) 1
redis> SCARD myset
(integer) 2

SPOP

SPOP key [count]

从set中删除并返回一个或者多个元素。注意,由于set内的元素是无序的,所以取出哪个元素实际是未定义行为,即可以看作随机的。
时间复杂度:O(N),n是count
返回值:取出的元素

java 复制代码
redis> SADD myset "one"
(integer) 1
redis> SADD myset "two"
(integer) 1
redis> SADD myset "three"
(integer) 1
redis> SPOP myset
"one"
redis> SMEMBERS myset
1) "three"
2) "two"
redis> SADD myset "four"
(integer) 1
redis> SADD myset "five"
(integer) 1
redis> SPOP myset 3
1) "three"
2) "four"
3) "two"
redis> SMEMBERS myset
1) "five"

SMOVE

SMOVE source destination member

将一个元素从 源set 取出并放入 目标set 中。
时间复杂度:O(1)
返回值:1 表示移动成功,0 表示失败

java 复制代码
 redis> SADD myset "one"
 (integer) 1
 redis> SADD myset "two"
 (integer) 1
 redis> SADD myotherset "three"
 (integer) 1
 redis> SMOVE myset myotherset "two"
 (integer) 1
 redis> SMEMBERS myset
 1) "one"
 redis> SMEMBERS myotherset
 1) "three"
 2) "two"

SREM

SREM key member [member ...]

将指定的元素从set中删除。
时间复杂度:O(N), N是要删除的元素个数.
返回值:本次操作删除的元素个数

java 复制代码
 redis> SADD myset "one"
 (integer) 1
 redis> SADD myset "two"
 (integer) 1
 redis> SADD myset "three"
 (integer) 1
 redis> SREM myset "one"
 (integer) 1
 redis> SREM myset "four"
 (integer) 0
 redis> SMEMBERS myset
 1) "three"
 2) "two"

集合间操作

交集(inter)、并集(union)、差集(diff)的概念如下图所示

集合求交集、并集、差集


SINTER

SINTER key [key ...]

获取给定set的交集中的元素
时间复杂度:O(N*M), N是最小的集合元素个数.M是最大的集合元素个数
返回值:交集的元素。

java 复制代码
 redis> SADD key1 "a"
 (integer) 1
 redis> SADD key1 "b"
 (integer) 1
  redis> SADD key1 "c"
 (integer) 1
 redis> SADD key2 "c"
 (integer) 1
 redis> SADD key2 "d"
 (integer) 1
 redis> SADD key2 "e"
 (integer) 1
 redis> SINTER key1 key2
 1) "c"

SINTERSTORE

SINTERSTORE destination key [key ...]

获取给定set的 交集 中的元素并 保存 到 目标set中
时间复杂度:O(N*M), N是最小的集合元素个数.M是最大的集合元素个数.
返回值:交集的元素个数

java 复制代码
 redis> SADD key1 "a"
 (integer) 1
 redis> SADD key1 "b"
 (integer) 1
 redis> SADD key1 "c"
 (integer) 1
 redis> SADD key2 "c"
 (integer) 1
 redis> SADD key2 "d"
 (integer) 1
 redis> SADD key2 "e"
 (integer) 1
 redis> SINTERSTORE key key1 key2
 (integer) 1
 redis> SMEMBERS key
 1) "c"

SUNION

SUNION key [key ...]

获取给定set的 并集 中的元素
时间复杂度:O(N),N给定的所有集合的总的元素个数.
返回值:并集的元素。

java 复制代码
 redis> SADD key1 "a"
 (integer) 1
 redis> SADD key1 "b"
 (integer) 1
 redis> SADD key1 "c"
 (integer) 1
 redis> SADD key2 "c"
 (integer) 1
 redis> SADD key2 "d"
 (integer) 1
 redis> SADD key2 "e"
 (integer) 1
 redis> SUNION key1 key2
 1) "a"
 2) "c"
 3) "e"
 4) "b"
 5) "d"

SUNIONSTORE

SUNIONSTORE destination key [key ...]

获取给定set的 并集 中的元素并保存到 目标set 中
时间复杂度:O(N), N给定的所有集合的总的元素个数.
返回值:并集的元素个数

java 复制代码
redis> SADD key1 "a"
 (integer) 1
 redis> SADD key1 "b"
 (integer) 1
 redis> SADD key1 "c"
 (integer) 1
 redis> SADD key2 "c"
 (integer) 1
 redis> SADD key2 "d"
 (integer) 1
 redis> SADD key2 "e"
 (integer) 1
 redis> SUNIONSTORE key key1 key2
 (integer) 5
 redis> SMEMBERS key
 1) "a"
 2) "c"
 3) "e"
 4) "b"
 5) "d"

SDIFF

SDIFF key [key ...]

获取给定set的差集中的元素
时间复杂度:O(N),N给定的所有集合的总的元素个数
返回值:差集的元素

java 复制代码
redis> SADD key1 "a"
(integer) 1
redis> SADD key1 "b"
(integer) 1
redis> SADD key1 "c"
(integer) 1
redis> SADD key2 "c"
(integer) 1
redis> SADD key2 "d"
(integer) 1
redis> SADD key2 "e"
(integer) 1
redis> SDIFF key1 key2
1) "a"
2) "b"

SDIFFSTORE

SDIFFSTORE destination key [key ...]

获取给定set的 差集 中的元素并保存到 目标set 中
时间复杂度:O(N),N给定的所有集合的总的元素个数
返回值:差集的元素个数

java 复制代码
redis> SADD key1 "a"
(integer) 1
redis> SADD key1 "b"
(integer) 1
redis> SADD key1 "c"
(integer) 1
redis> SADD key2 "c"
(integer) 1
redis> SADD key2 "d"
(integer) 1
redis> SADD key2 "e"
(integer) 1
redis> SDIFFSTORE key key1 key2
(integer) 2
redis> SMEMBERS key
 1) "a"
 2) "b"

命令小结


内部编码

集合类型的内部编码有两种:

  • intset(整数集合):当集合中的元素都是整数并且元素的个数小于 set-max-intset-entries 配置(默认512个)时,Redis会选用 intset 来作为集合的内部实现,从而减少内存的使用。
  • hashtable(哈希表):当集合类型无法满足 intset 的条件时,Redis会使用 hashtable 作为集合的内部实现。

(1) 当元素个数较少并且都为整数时,内部编码为intset

java 复制代码
127.0.0.1:6379> sadd setkey 1 2 3 4
(integer) 4
127.0.0.1:6379> object encoding setkey
"intset"

(2) 当元素个数超过512个,内部编码为 hashtable

java 复制代码
 127.0.0.1:6379> sadd setkey 1 2 3 4
 (integer) 513
 127.0.0.1:6379> object encoding setkey
 "hashtable"

(3) 当存在元素不是整数时,内部编码为 hashtable

java 复制代码
127.0.0.1:6379> sadd setkey a
(integer) 1
127.0.0.1:6379> object encoding setkey
"hashtable"

使用场景

集合类型比较典型的使用场景是标签(tag)。
例如A用户对娱乐、体育板块比较感兴趣,B用户对历史、新闻比较感兴趣,这些兴趣点可以被抽象为标签。有了这些数据就可以得到喜欢同一个标签的人,以及用户的共同喜好的标签,这些数据对于增强用户体验和用户黏度都非常有帮助。
例如一个电子商务网站会对不同标签的用户做不同的产品推荐

通过集合类型来实现标签的若干功能

(1) 给用户添加标签

java 复制代码
sadd user:1:tags tag1 tag2 tag5
sadd user:2:tags tag2 tag3 tag5
...
sadd user:k:tags tag1 tag2 tag4

(2) 给标签添加用户

java 复制代码
sadd tag1:users user:1 user:3
sadd tag2:users user:1 user:2 user:3
...
sadd tagk:users user:1 user:4 user:9 user:28

(3) 删除用户下的标签

java 复制代码
srem user:1:tags tag1 tag5
...

(4) 删除标签下的用户

java 复制代码
srem tag1:users user:1
srem tag5:users user:1
...

(5) 计算用户的共同兴趣标签

java 复制代码
sinter user:1:tags user:2:tags

相关推荐
xuxie1336 分钟前
SpringBoot文件下载(多文件以zip形式,单文件格式不变)
java·spring boot·后端
白鹭37 分钟前
MySQL源码部署(rhel7)
数据库·mysql
重生成为编程大王1 小时前
Java中的多态有什么用?
java·后端
666和7771 小时前
Struts2 工作总结
java·数据库
还听珊瑚海吗1 小时前
SpringMVC(一)
数据库
中草药z1 小时前
【Stream API】高效简化集合处理
java·前端·javascript·stream·parallelstream·并行流
野犬寒鸦1 小时前
力扣hot100:搜索二维矩阵 II(常见误区与高效解法详解)(240)
java·数据结构·算法·leetcode·面试
zru_96021 小时前
centos 系统如何安装open jdk 8
java·linux·centos
LiRuiJie2 小时前
深入剖析Spring Boot / Spring 应用中可自定义的扩展点
java·spring boot·spring