set集合中的元素是唯一的、无序的;
命令 | 时间复杂度 |
---|---|
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(n),n 是 count |
spop key [count] | O(n),n 是 count |
smembers key | O(k),k 是元素个数 |
sinter key [key ...] sitnerstore | O(m * k),k 是多个集合中元素最小的个数,m 是键个数 |
sunion key [key ...] sunionstore | O(k),k 是多个集合的元素个数总和 |
sdiff key [key ...] sdiffstore | O(k),k 是多个集合的元素个数总和 |
相关命令:
sadd:
向集合中添加元素,返回的是成功添加的元素个数,不是添加后set中元素的个数,因为元素是唯一的所以一些重复的元素不会添加成功。
sadd key member [member ...]
// 向集合中插入元素,为了和别的数据类型做区分,
// 这里使用number这个单词代表set中的元素,
// 它和list中的element一样都是String类型
// hash中的元素叫field,string的元素叫value
smembers:
smembers key // 查看set中所有的元素
元素展示的顺序就是添加时的顺序!!
sismember:
sismember number key // 判断某个元素是否在set内。(1 true,0 false)
scard:
scard key // 集合中元素的个数
spop:
pop一般表示尾删,但是set是无序的,并没有所谓的“尾部元素”。spop删除的其实是set中一个随机的元素。
spop key count // 随机删除set中count个元素,不加count默认随机删除一个
可以看出对于两个相同的set使用spop,被删除的元素顺序不一样,说明spop删除元素是完全随机的。
smove:
smove source destination member
// 将某一个元素从一个set集合中移动到另外一个set集合中
// 效果等价于从source中删除member再将member添加到destination中
// 如果member在source中不存在,那么就会返回0,成功返回1
srem:
srem key number [number ...]
// 删除set集合中指定元素
// 返回被删除成功的元素个数
// 删除set中不存在的member同样是软着陆的处理方式,并不会报错
交集inter:
sinter key [key ...] // 返回值是这些集合的交集,但不会修改这些集合
sinterstore destination key [key ...] // 创建一个新的集合存储相交后的结果,返回值是交集元素的个数
并集union:
sunion key [key ...] //返回值是这些集合的并集,且不会改变这些集合
sunionstore destination key [key ...] //创建一个新的集合去存储并集结果,返回值会并集的元素个数
差集diff:
什么是差集:对于sdiff key key1 key2 key3 key4的运算结果为下图黄色区域:
sdiff key [key ...] //返回值是这些集合的差集,且不会改变这些集合
sdiff destination key [key ...] //创建一个新的集合去存储差集结果,返回值会差集的元素个数
编码方式:
集合类型的内部编码有两种:
- intset(整数集合):当集合中的元素都是整数并且元素的个数⼩于 set-max-intset-entries 配置 (默认 512 个)时,Redis 会选⽤ intset 来作为集合的内部实现,从⽽减少内存的使⽤。
- hashtable(哈希表):当集合类型⽆法满⾜ intset 的条件时,Redis 会使⽤ hashtable 作为集合 的内部实现。
C++中的 std::set底层的数据结构是红黑树,java中的set本身是一个接口,背后的实现可能是TreeSet或者是HashSet。
应用场景:
1、保存用户标签:
很多app都会搜集用户信息,给用户打上一些标签,为客户精准推送内容。这样的一种标签就适合存储在set中,因为标签刚好满足无序性,唯一性。比如用户的年龄段,兴趣爱好、地区等等,将这些标签存储在redis中。除了用户有标签,博客也有标签比如redis、数据库、缓存等标签,意思是一样的。
2、使用Set来计算共同好友:
基于集合的交集运算就可以求出共同好友。
3、使用Set统计UV
对于一个互联网产品,我们一般有两个指标去描述产品的用户规模:
- PV:用户每访问一次服务器,就会产生一个PV;
- UV:每个用户访问服务器只会产生一个UV,并不会产生多个UV
可以使用int去存储PV的值;使用set中元素的个数去描述UV,每次用户访问服务器都将用户id添加到set当中,因为set中元素是唯一的,所以某一个用户多次访问服务器也只会产生一个UV;(PV& UV一般是在某个时间范围内去统计的)