谈到一个术语,这个术语很可能有多种含义~~
1.Set
1) 集合.
2)设置 (和 get 相对应)
集合就是把一些有关联的数据放到一起~~
1.集合中的元素是无序的!
【此处说的无序和 前面list这里的有序 是对应的,
有序: 顺序很重要. 变换一下顺序, 就是不同的 list 了
无序: 顺序不重要.变化一下顺序,集合还是那个集合,
list: [1,2, 3]和 [2,1,3]两个不同的 list
set: [1,2,3] 和 [2,1,3]是同一个集合】
2.集合中的元素是不能重复的(唯一的)
和 list 类似, 集合中的每个元素也都是 string 类型
(可以使用 json 这样的格式让 string 也能存储 结构化 数据)
2.set的普通命令
2.1 SADD
将⼀个或者多个元素添加到 set 中。注意,重复的元素⽆法添加到 set 中。
语法:
SADD key member [member ...]
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值:本次添加成功的元素个数。不能重复的特性!!!
⽰例:
redis> SADD myset "Hello"(integer) 1redis> SADD myset "World"(integer) 1redis> SADD myset "World"(integer) 0redis> SMEMBERS myset1) "Hello"2) "World"
2.2 SMEMBERS
获取⼀个 set 中的所有元素,注意,元素间的顺序是⽆序的。
语法:
SMEMBERS key
命令有效版本:1.0.0 之后时间复杂度:O(N)返回值:所有元素的列表。
⽰例:
redis> SADD myset "Hello"(integer) 1redis> SADD myset "World"(integer) 1redis> SMEMBERS myset1) "Hello"2) "World"
2.3 SISMEMBER
判断⼀个元素在不在 set 中。
语法:
SISMEMBER key member
命令有效版本:1.0.0 之后时间复杂度:O(1)返回值:1 表⽰元素在 set 中。0 表⽰元素不在 set 中或者 key 不存在。
示例:
redis> SADD myset "one"(integer) 1redis> SISMEMBER myset "one"(integer) 1redis> SISMEMBER myset "two"(integer) 0
2.4 SCARD
获取⼀个 set 的基数(cardinality),即 set 中的元素个数。
语法:
SCARD key
命令有效版本:1.0.0 之后时间复杂度:O(1)返回值:set 内的元素个数。
⽰例:
redis> SADD myset "Hello"(integer) 1redis> SADD myset "World"(integer) 1redis> SCARD myset(integer) 2
2.5 SPOP
从 set 中删除并返回⼀个或者多个元素。注意,由于 set 内的元素是⽆序【逻辑是无序的】的,所以取出哪个元素实际是未定义⾏为,即可以看作随机的。(随机进行删除)
语法:
SPOP key [count]
命令有效版本:1.0.0 之后时间复杂度:O(N), n 是 count返回值:取出的元素。
⽰例:
redis> SADD myset "one"(integer) 1redis> SADD myset "two"(integer) 1redis> SADD myset "three"(integer) 1redis> SPOP myset"one"redis> SMEMBERS myset1) "three"2) "two"redis> SADD myset "four"(integer) 1redis> SADD myset "five"(integer) 1redis> SPOP myset 31) "three"2) "four"3) "two"redis> SMEMBERS myset1) "five"
2.6 SMOVE
将⼀个元素从源 set 取出并放⼊⽬标 set 中。
语法:
SMOVE source destination member
命令有效版本:1.0.0 之后时间复杂度:O(1)返回值:1 表⽰移动成功,0 表⽰失败。
⽰例:
redis> SADD myset "one"(integer) 1redis> SADD myset "two"(integer) 1redis> SADD myotherset "three"(integer) 1redis> SMOVE myset myotherset "two"(integer) 1redis> SMEMBERS myset1) "one"redis> SMEMBERS myotherset1) "three"2) "two"
2.7 SREM
将指定的元素从 set 中删除。
语法:
SREM key member [member ...]
命令有效版本:1.0.0 之后时间复杂度:O(N), N 是要删除的元素个数.返回值:本次操作删除的元素个数。
⽰例:
redis> SADD myset "one"(integer) 1redis> SADD myset "two"(integer) 1redis> SADD myset "three"(integer) 1redis> SREM myset "one"(integer) 1redis> SREM myset "four"(integer) 0redis> SMEMBERS myset1) "three"2) "two"
3.集合间操作
交集(inter)、并集(union)、差集(diff)
3.1 SINTER(交集)
获取给定 set 的交集中的元素。
语法:
SINTER key [key ...]
命令有效版本:1.0.0 之后时间复杂度:O(N * M), N 是最⼩的集合元素个数. M 是最⼤的集合元素个数.返回值:交集的元素。
⽰例:
redis> SADD key1 "a"(integer) 1redis> SADD key1 "b"(integer) 1redis> SADD key1 "c"(integer) 1redis> SADD key2 "c"(integer) 1redis> SADD key2 "d"(integer) 1redis> SADD key2 "e"(integer) 1redis> SINTER key1 key21) "c"
3.2 SINTERSTORE(交集并保存起来)
获取给定 set 的交集中的元素并保存到⽬标 set 中。
语法:
SINTERSTORE destination key [key ...]
命令有效版本:1.0.0 之后时间复杂度:O(N * M), N 是最⼩的集合元素个数. M 是最⼤的集合元素个数.返回值:交集的元素个数。
⽰例:
redis> SADD key1 "a"(integer) 1redis> SADD key1 "b"(integer) 1redis> SADD key1 "c"(integer) 1redis> SADD key2 "c"(integer) 1redis> SADD key2 "d"(integer) 1redis> SADD key2 "e"(integer) 1redis> SINTERSTORE key key1 key2(integer) 1redis> SMEMBERS key1) "c"
3.3 SUNION
获取给定 set 的并集中的元素。
语法:
SUNION key [key ...]
命令有效版本:1.0.0 之后时间复杂度:O(N), N 给定的所有集合的总的元素个数.返回值:并集的元素。
⽰例:
redis> SADD key1 "a"(integer) 1redis> SADD key1 "b"(integer) 1redis> SADD key1 "c"(integer) 1redis> SADD key2 "c"(integer) 1redis> SADD key2 "d"(integer) 1redis> SADD key2 "e"(integer) 1redis> SUNION key1 key21) "a"2) "c"3) "e"4) "b"5) "d"
3.4 SUNIONSTORE
获取给定 set 的并集中的元素并保存到⽬标 set 中。
语法:
SUNIONSTORE destination key [key ...]
命令有效版本:1.0.0 之后时间复杂度:O(N), N 给定的所有集合的总的元素个数.返回值:并集的元素个数。
⽰例:
redis> SADD key1 "a"(integer) 1redis> SADD key1 "b"(integer) 1redis> SADD key1 "c"(integer) 1redis> SADD key2 "c"(integer) 1redis> SADD key2 "d"(integer) 1redis> SADD key2 "e"(integer) 1redis> SUNIONSTORE key key1 key2(integer) 5redis> SMEMBERS key1) "a"2) "c"3) "e"4) "b"5) "d"
3.5 SDIFF
获取给定 set 的差集中的元素。
语法:
SDIFF key [key ...]
命令有效版本:1.0.0 之后时间复杂度:O(N), N 给定的所有集合的总的元素个数.返回值:差集的元素。
⽰例:
1 redis> SADD key1 "a"(integer) 1redis> SADD key1 "b"(integer) 1redis> SADD key1 "c"(integer) 1redis> SADD key2 "c"(integer) 1redis> SADD key2 "d"(integer) 1redis> SADD key2 "e"(integer) 1redis> SDIFF key1 key21) "a"2) "b"
3.6 SDIFFSTORE
获取给定 set 的差集中的元素并保存到⽬标 set 中。
语法:
SDIFFSTORE destination key [key ...]
命令有效版本:1.0.0 之后时间复杂度:O(N), N 给定的所有集合的总的元素个数.返回值:差集的元素个数。
⽰例:
redis> SADD key1 "a"(integer) 1redis> SADD key1 "b"(integer) 1redis> SADD key1 "c"(integer) 1redis> SADD key2 "c"(integer) 1redis> SADD key2 "d"(integer) 1redis> SADD key2 "e"(integer) 1redis> SDIFFSTORE key key1 key2(integer) 2redis> SMEMBERS key1) "a"2) "b"
4.命令小节
命令 | 时间复杂度 |
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 是多个集合的元素个数总和 |
5.set内部编码
- intset(整数集合)为了节省空间,做出的特定优化~
- 当元素均为整数,并且元素个数不是很多的时候
- hashtable(哈希表)
- C++ 中的 std:.set 背后的数据结构是 红黑树Java 中的 Set 本身是一个接口.这个接口后面的实现,可以是 Treeset, 也可以是 HashSet
6.set的应用场景
6.1 添加标签
集合类型⽐较典型的使⽤场景是标签(tag)。例如 A ⽤⼾对娱乐、体育板块⽐较感兴趣,B ⽤⼾
对历史、新闻⽐较感兴趣,这些兴趣点可以被抽象为标签。有了这些数据就可以得到喜欢同⼀个标签的⼈,以及⽤⼾的共同喜好的标签,这些数据对于增强⽤⼾体验和⽤⼾黏度都⾮常有帮助。 例如⼀个电⼦商务⽹站会对不同标签的⽤⼾做不同的产品推荐。
下⾯的演⽰通过集合类型来实现 标签 的若⼲功能。
1)给⽤⼾添加标签
2)给标签添加⽤⼾
3)删除⽤⼾下的标签
4)删除标签下的⽤⼾
5)计算⽤⼾的共同兴趣标签
6.2. 使用 Set 来计算用户之间的共同好友
~~基于"集合求交集”
QQ,
我这边加了很多好友.你这边也加了很多好友~~
基于上述还可以做一些好友推荐~~
A 和 B 是好友,
A 和 C 是好友.
B 和C和 D 都是好友.
系统就会把 D 推荐给 A
6.3.使用 Set 统计 UV
去重~~
一个互联网产品,如何衡量用户量,用户规模??主要的指标,是两方面:
1.PV page view
用户每次访问该服务器,每次访问都会产生一个 pv
2.UV user view
每个用户,访问服务器,都会产生一个 uv.但是同一个用户多次访问, 不会使 uv 增加~~uv 需要按照用户进行去重~~
上述的去重过程,就可以使用 set 来实现.