区间 | 命令 | 功能 | 时间复杂度 |
集合内 | sadd key element [element ... ] | 添加元素 | O(k),k是元素个数 |
srem key element [element ... ] | 删除元素 | O(k),k是元素个数 | |
scard key | 计算元素个数 | O(1) | |
sismember key element | 判断元素是否在集合中 | O(1) | |
srandmember key [count] | 随机返回指定个数个元素 | O(count) | |
spop key | 随机弹出元素 | O(1) | |
smembers key | 获取所有元素 | O(n),n是元素总数 | |
集合间 | sinter key [key ... ] | 取交集 | O(m*k),k是多集合中元素最少的个数,m是键数 |
sunion key [key ... ] | 取并集 | O(k),k是多个集合元素个数和 | |
sdiff key [key ... ] | 取差集 | O(k),k是多个集合元素个数和 | |
sinterstore destination key [key ... ] | 保存交集 | O(m*k),k是多集合中元素最少的个数,m是键数 | |
sunionstore destination key [key ... ] | 保存并集 | O(k),k是多个集合元素个数和 | |
sdiffstore destination key [key ... ] | 保存差集 | O(k),k是多个集合元素个数和 |
集合(set)类型也是用来保存多个字符串元素的,但和列表类型不一样的是,
集合中不允许有重复元素,并且集合中的元素是无序的,不能通过索引下标获取元素。
,如下图所示,集合set:1包含着“a”、“b”、“c“四个元素,一个集合最多可以存储2**32 -1个元素。
Redis除了支持集合内的增删改查,同时还支持多个集合取交集、并集、差集,合理地使用好集合类型,能在实际开发中解决很多问题。
下面按照集合内和集合间两个维度对集合的常用命令进行介绍。
1.集合内操作
(1)添加元素
命令:sadd key element [element ...]
返回结果为添加成功的元素个数:
127.0.0.1:6379> exists set:1 #查看键是否存在 (integer) 0 127.0.0.1:6379> sadd set:1 a b c (integer) 3 #添加了3个元素 127.0.0.1:6379> sadd set:1 a b d (integer) 1 #集合不允许重复,只添加了一个 127.0.0.1:6379> smembers set:1 #查看结果 1) "b" 2) "a" 3) "d" 4) "c"
(2)删除元素
命令:srem key element [element ... ]
返回结果为成功删除元素个数
127.0.0.1:6379> smembers set:1 1) "b" 2) "a" 3) "d" 4) "c" 127.0.0.1:6379> srem set:1 a (integer) 1 127.0.0.1:6379> smembers set:1 1) "b" 2) "d" 3) "c"
(3)计算元素个数
命令:scard key
scard的时间复杂度为O(1),它不会遍历集合所有元素,而是直接用Redis内部的变量:
127.0.0.1:6379> smembers set:1 1) "b" 2) "a" 3) "d" 4) "c" 127.0.0.1:6379> scard set:1 (integer) 4
(4)判断元素是否在集合中
命令:sismember key element
如果给定元素element在集合内返回1,反之返回0:
127.0.0.1:6379> smembers set:1 1) "b" 2) "d" 3) "c" 127.0.0.1:6379> sismember set:1 b (integer) 1 127.0.0.1:6379> sismember set:1 e (integer) 0
(5)随机从集合返回指定个数元素
命令:srandmember key [count]
[count]是可选参数,如果不写默认为1:
127.0.0.1:6379> smembers set:1 1) "b" 2) "d" 3) "c" 127.0.0.1:6379> srandmember set:1 "d" 127.0.0.1:6379> srandmember set:1 2 1) "c" 2) "d"
(6)从集合随机弹出元素
命令:spop key
spop操作可以从集合中随机弹出一个元素:
127.0.0.1:6379> smembers set:1 1) "a" 2) "c" 3) "e" 4) "d" 5) "b" 127.0.0.1:6379> spop set:1 "a" 127.0.0.1:6379> spop set:1 "b" 127.0.0.1:6379> smembers set:1 1) "c" 2) "e" 3) "d"
需要注意的是Redis从3.2版本开始,spop也支持[count]参数。
srandmember和spop都是随机从集合选出元素,两者不同的是spop命令执行后,元素会从集合中删除,而srandmember不会。
(7)获取所有元素
命令:smembers key
smembers会获取所有元素,但是返回的结果是无序的:
127.0.0.1:6379> smembers set:1 1) "c" 2) "e" 3) "d"
smembers和lrange、hgetall都属于比较重的命令,如果元素过多存在阻塞Redis的可能性,这时候可以使用sscan来完成。
2.集合间操作
现在有两个集合:
127.0.0.1:6379> smembers set:1 1) "c" 2) "e" 3) "d" 127.0.0.1:6379> smembers set:2 1) "b" 2) "d" 3) "c"
(1)求多个集合的交集
命令:sinter key [key ... ]
127.0.0.1:6379> sinter set:1 set:2 #双方都有的 1) "c" 2) "d"
(2)求多个集合的并集
命令:sunion key [key ... ]
127.0.0.1:6379> sunion set:1 set:2 1) "d" 2) "e" 3) "c" 4) "b"
(3)求多个集合的差集
命令:sdiff key [key ...]
127.0.0.1:6379> sdiff set:1 set:2 #set:2相对于set:1的差集 1) "e" 127.0.0.1:6379> sdiff set:2 set:1 #set:1相对于set:2的差集,也就是set:2有set:1没有的 1) "b"
(4)将交集、并集、差集的结果保存
命令:
sinterstore destination key [key ... ]
sunionstore destination key [key ...]
sdiffstore destination key [key ... ]
集合间的运算在元素较多的情况下会比较耗时,所以Redis提供了上面三个命令(原命令+store)将集合间交集、并集、差集保存在destination key中:
#保存交集 127.0.0.1:6379> sinterstore set:sinter:1_2 set:1 set:2 (integer) 2 127.0.0.1:6379> smembers set:sinter:1_2 1) "d" 2) "c" #保存并集 127.0.0.1:6379> sunionstore set:sunion:1_2 set:1 set:2 (integer) 4 127.0.0.1:6379> smembers set:sunion:1_2 1) "d" 2) "e" 3) "c" 4) "b" #保存差集 127.0.0.1:6379> sdiffstore set:sdiff:1_2 set:1 set:2 (integer) 1 127.0.0.1:6379> smembers set:sdiff:1_2 1) "e" 127.0.0.1:6379> sdiffstore set:sdiff:2_1 set:2 set:1 (integer) 1 127.0.0.1:6379> smembers set:sdiff:2_1 1) "b"