Set 集合
集合类型也是保存多个字符串类型的元素的,但和列表类型不同的是,集合中元素之间是无序的且元素不允许重复。
一个集合中最多可以存储 232−12^32^ - 1232−1 个元素。
Redis 除了支持集合内的增删查改操作,同时还支持多个集合取交集、并集、差集,合理地使用好集合类型,能在实际开发中解决很多问题。
普通命令
SADD
将一个或者多个元素添加到 set 中。注意,重复的元素无法添加到 set 中。
- 语法:
SADD key member [member ...]
- 命令有效版本:1.0.0 之后
- 时间复杂度:O(1)
- 返回值:本次添加成功的元素个数。
- 示例:
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
获取一个 set 中的所有元素,注意,元素间的顺序是无序的。
- 语法:
SMEMBERS key
- 命令有效版本:1.0.0 之后
- 时间复杂度:O(N)
- 返回值:所有元素的列表。
- 示例:
redis> SADD myset "Hello"
(integer) 1
redis> SADD myset "World"
(integer) 1
redis> SMEMBERS myset
1) "Hello"
2) "World"
SISMEMBER
判断一个元素在不在 set 中。
- 语法:
SISMEMBER key member
- 命令有效版本:1.0.0 之后
- 时间复杂度:O(1)
- 返回值:1 表示元素在 set 中。0 表示元素不在 set 中或者 key 不存在。
- 示例:
redis> SADD myset "one"
(integer) 1
redis> SISMEMBER myset "one"
(integer) 1
redis> SISMEMBER myset "two"
(integer) 0
SCARD
获取一个 set 的基数(cardinality),即 set 中的元素个数。
- 语法:
SCARD key
- 命令有效版本:1.0.0 之后
- 时间复杂度:O(1)
- 返回值:set 内的元素个数。
- 示例:
redis> SADD myset "Hello"
(integer) 1
redis> SADD myset "World"
(integer) 1
redis> SCARD myset
(integer) 2
SPOP
从 set 中删除并返回一个或者多个元素。注意,由于 set 内的元素是无序的,所以取出哪个元素实际是未定义行为,即可以看作随机的。
- 语法:
SPOP key [count]
- 命令有效版本:1.0.0 之后
- 时间复杂度:O(N),n 是 count
- 返回值:取出的元素。
- 示例:
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
将一个元素从源 set 取出并放入目标 set 中。
- 语法:
SMOVE source destination member
- 命令有效版本:1.0.0 之后
- 时间复杂度:O(1)
- 返回值:1 表示移动成功,0 表示失败。
- 示例:
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
将指定的元素从 set 中删除。
- 语法:
SREM key member [member ...]
- 命令有效版本:1.0.0 之后
- 时间复杂度:O(N),N 是要删除的元素个数
- 返回值:本次操作删除的元素个数。
- 示例:
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"
集合间操作
SINTER
获取给定 set 的交集中的元素。
- 语法:
SINTER key [key ...]
- 命令有效版本:1.0.0 之后
- 时间复杂度:O(N * M),N 是最小的集合元素个数,M 是最大的集合元素个数
- 返回值:交集的元素。
- 示例:
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
获取给定 set 的交集中的元素并保存到目标 set 中。
- 语法:
SINTERSTORE destination key [key ...]
- 命令有效版本:1.0.0 之后
- 时间复杂度:O(N * M),N 是最小的集合元素个数,M 是最大的集合元素个数
- 返回值:交集的元素个数。
- 示例:
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
获取给定 set 的并集中的元素。
- 语法:
SUNION key [key ...]
- 命令有效版本:1.0.0 之后
- 时间复杂度:O(N),N 给定的所有集合的总的元素个数
- 返回值:并集的元素。
- 示例:
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) "b"
4) "d"
5) "e"
SUNIONSTORE
获取给定 set 的并集中的元素并保存到目标 set 中。
- 语法:
SUNIONSTORE destination key [key ...]
- 命令有效版本:1.0.0 之后
- 时间复杂度:O(N),N 给定的所有集合的总的元素个数
- 返回值:并集的元素个数。
- 示例:
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) "b"
4) "d"
5) "e"
SDIFF
获取给定 set 的差集中的元素。
- 语法:
SDIFF key [key ...]
- 命令有效版本:1.0.0 之后
- 时间复杂度:O(N),N 给定的所有集合的总的元素个数
- 返回值:差集的元素。
- 示例:
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
获取给定 set 的差集中的元素并保存到目标 set 中。
- 语法:
SDIFFSTORE destination key [key ...]
- 命令有效版本:1.0.0 之后
- 时间复杂度:O(N),N 给定的所有集合的总的元素个数
- 返回值:差集的元素个数。
- 示例:
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"
总结
命令 | 时间复杂度 |
---|---|
sadd key element [element …] | O(k),k 是元素个数 |
srem key element [element …] | O(k),k 是元素个数 |
scard key | O(1) |
sismember key element | O(1) |
sprandmember key [count] | O(n),n 是 count |
spop key [count] | O(n),n 是 count |
smembers key | O(k),k 是元素个数 |
sinter key [key …] sinterstore | O(m * k),k 是几个集合中元素最小的个数,m 是键个数 |
sunion key [key …] sunionstore | O(k),k 是多个集合的元素个数总和 |
sdiff key [key …] sdiffstore | O(k),k 是多个集合的元素个数总和 |
内部编码
集合类型的内部编码有两种:
- intset(整数集合):当集合中的元素都是整数并且元素的个数小于 set - max - intset - entries 配置(默认 512 个)时,Redis 会选用 intset 来作为集合的内部实现,从而减少内存的使用。
- hashtable(哈希表):当集合类型无法满足 intset 的条件时,Redis 会使用 hashtable 作为集合的内部实现。
- 当元素个数较少并且都为整数时,内部编码为 intset:
127.0.0.1:6379> sadd setkey 1 2 3 4
(integer) 4
127.0.0.1:6379> object encoding setkey
"intset"
- 当元素个数超过 512 个,内部编码为 hashtable:
127.0.0.1:6379> sadd setkey 1 2 3 4
(integer) 513
127.0.0.1:6379> object encoding setkey
"hashtable"
- 当存在元素不是整数时,内部编码为 hashtable:
127.0.0.1:6379> sadd setkey a
(integer) 1
127.0.0.1:6379> object encoding setkey
"hashtable"