这篇我们来看看Redis五大类型中的第四大类型:“集合类型”,集合类型还是蛮有意思的,第一个是因为它算是只使用key的Dictionary简易版,
这样说来的话,它就比Dictionary节省很多内存消耗,第二个是因为它和C#中的HashSet是一个等同类型,废话不多说,先看redis手册,如下:

上面就是redis中的set类型使用到的所有方法,还是老话,常用的方法也就那么四个(CURD)。。。
方法
这个方法毫无疑问,就是向集合里面添加数据,比如下面这样,我往fruits集合里面添加喜爱的水果。
.:>
.:>
.:>)
)
.:>

上面这个sadd你也看到了,我往集合里面成功添加了两个元素,现在你可能不满足这么简单的添加,你或许想知道set这个集合在redis底层是使用
什么来实现的,你可以用object encoding查看一下便知:
.:>
.:>
看到了吧,是hashtable这个吊毛,现在闭上眼睛都能想到,肯定就是只用key的dictionary啦,对不对,如果你还有疑问的话,我还可以找到底层
代码给你看,好不啦???

有没有看到dictAdd方法,而其中的第三个参数正好是Null。。。对应着*val形参,你看牛叉不牛叉。。。然后我再带你看看dictAdd方法的定义。

好了,关于hashtable的实现理论,我在上一篇文章中也已经说过了,这里就不再赘叙了。
既然元素进来了,总不能不出来吧,这里的第一个SPOP:一个随机元素,有一点奇怪的是,这种奇怪的方法其实在我们
C#中的HashSet并没有好办法解决,就比如”这个随机“就有点烦人了,下面这是我能想到的方法。

刚才随便插了一句话,下面我们继续SAdd,再SPop出来。
.:>
.:>
.:>
.:>)
)
)
)
)
.:>
.:>
.:>)
)
)
.:>

这个方法确实还是蛮好的,起码它是原子性操作,如果要我自己实现的话,起码还是要10行左右代码的。
既然说到了CURD,那怎么能少了D呢,它的功能定义就是:一个或多个 member 元素,不存在的 member 元素会被忽略,
下面我随便举个例子,删除fruits中的pear。
.:>)
)
)
.:>
.:>)
)
.:>
404.png" alt="">
方法是简单的,关键你需要了解这个方法底层是如何实现的,这样才能做到
就比如set函数,它的源代码全部都在 “t.set.c” 中。
display: none;" onclick="cnblogs_code_hide('ddb7681e-3da0-4aeb-8cfc-5004814a1346',event)" src="/res/2019/02-17/00/405b18b4b6584ae338e0f6ecaf736533.gif" alt="">
copyright (c) 2009-2012,Salvatore Sanfilippo
distribution and use in source and binary forms,with or without
distributions of source code must retain the above copyright notice, disclaimer.
distributions in binary form must reproduce the above copyright
disclaimer in the
distribution.
dis nor the names of its contributors may be used
copYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
fitness FOR A PARTIculaR PURPOSE
disCLaimED. IN NO EVENT SHALL THE copYRIGHT OWNER OR CONTRIBUTORS BE
damAGES (INCLUDING,PROCUREMENT OF
nesS
damAGE.
#include dis.h
sunionDiffGenericCommand(redisClient *c,robj **setkeys, setnum,robj *dstkey,
encodable value,an intset will be returned. Otherwise a regular
robj *setTypeCreate(robj * (isObjectRepresentableAsLongLong(value,NULL) ==dis_OK)
etobject();
etobject();
setTypeAdd(robj *subject,robj * (subject->encoding ==dis_ENCODING_HT) {
(dictAdd(subject->ptr,value,NULL) == } (subject->encoding ==dis_ENCODING_INTSET) {
(isObjectRepresentableAsLongLong(value,&llval) ==dis_OK) {
uint8_t success = subject->ptr = intsetAdd(subject->ptr,llval,&
(intsetLen(subject->ptr) > dis_ENCODING_HT);
} Failed to get integer from object,convert to regular set.
dis_ENCODING_HT);
encodable,so dictAdd should always work.
redisAssertWithInfo(NULL,dictAdd(subject->ptr,NULL) == } redisPanic(Nown set encoding
setTypeRemove(robj *setobj,robj * (setobj->encoding ==dis_ENCODING_HT) {
(dictDelete(setobj->ptr,value) == (htNeedsResize(setobj->ptr)) dictResize(setobj-> } (setobj->encoding ==dis_ENCODING_INTSET) {
(isObjectRepresentableAsLongLong(value,&llval) ==dis_OK) {
setobj->ptr = intsetRemove(setobj->ptr,& (success) } redisPanic(Nown set encoding
setTypeIsMember(robj *subject,robj * (subject->encoding ==dis_ENCODING_HT) {
dictFind((dict*)subject->ptr,value) != } (subject->encoding ==dis_ENCODING_INTSET) {
(isObjectRepresentableAsLongLong(value,&llval) ==dis_OK) {
intsetFind((intset*)subject-> }