redis-06 五大基本类型之Set
目录概述
Redis 中的集合最多存储 232 - 1 个元素,具备固有集合的性质(唯一性、无序性),Redis 中的集合是通过 Hash Table 数据结构实现的,增删查的时间复杂度都是 $O(1)$,其中最方便的一点还是支持集合间的运算。
命令
增、删、查、判断是否存在
- sadd
- srem
- sismember
- 判断元素是否存在于集合中
- 返回是否存在
- smembers
- 查看所有元素
- 返回元素集合
@Test
public void basicoperationOnSet() {
long effected = j.sadd("numbers", "1", "2", "3");
assertEquals(3L, effected);
effected = j.sadd("numbers", "3", "4", "5");
assertEquals(2L, effected);
effected = j.srem("numbers", "1", "2");
assertEquals(2L, effected);
boolean rel = j.sismember("numbers", "1");
assertFalse(rel);
rel = j.sismember("numbers", "3");
assertTrue(rel);
Set<String> numbers = j.smembers("numbers");
assertEquals(3, numbers.size());
assertTrue(numbers.contains("3"));
assertTrue(numbers.contains("4"));
assertTrue(numbers.contains("5"));
}
集合运算
差
- sdiff
- 参数依次是 A、B、C 三个集合
- 结果是 A - B - C
- 返回运算结果集合,不存储
@Test
public void setDiff() {
// if you want to store the result into other key, just append "store" behind the command
long effected = j.sadd("setA", "1", "2", "3");
assertEquals(3L, effected);
effected = j.sadd("setB", "3", "4", "5");
assertEquals(3L, effected);
effected = j.sadd("setC", "2", "5", "6");
assertEquals(3L, effected);
// A - B
Set<String> diffs = j.sdiff("setA", "setB");
assertEquals(2, diffs.size());
assertTrue(diffs.contains("1"));
assertTrue(diffs.contains("2"));
// A - B - C
diffs = j.sdiff("setA", "setB", "setC");
assertEquals(1, diffs.size());
assertTrue(diffs.contains("1"));
}
交
- sinter
- 参数依次是 A、B、C 三个集合
- 结果是 $A \cap B \cap C$
- 返回运算结果集合,不存储
@Test
public void setInter() {
// if you want to store the result into other key, just append "store" behind the command
long effected = j.sadd("setA", "1", "2", "3");
assertEquals(3L, effected);
effected = j.sadd("setB", "3", "4", "5");
assertEquals(3L, effected);
effected = j.sadd("setC", "2", "3", "6");
assertEquals(3L, effected);
Set<String> inters = j.sinter("setA", "setB", "setC");
assertEquals(1, inters.size());
assertTrue(inters.contains("3"));
}
并
- sunion
- 参数依次是 A、B、C 三个集合
- 结果是 $A \cup B \cup C$
- 返回运算结果集合,不存储
@Test
public void setUnion() {
// if you want to store the result into other key, just append "store" behind the command
long effected = j.sadd("setA", "1", "2", "3");
assertEquals(3L, effected);
effected = j.sadd("setB", "3", "4", "5");
assertEquals(3L, effected);
effected = j.sadd("setC", "2", "3", "6");
assertEquals(3L, effected);
Set<String> union = j.sunion("setA", "setB", "setC");
assertNotNull(union);
assertEquals(6, union.size());
assertTrue(union.contains("6"));
assertTrue(union.contains("5"));
assertTrue(union.contains("4"));
assertTrue(union.contains("3"));
assertTrue(union.contains("2"));
assertTrue(union.contains("1"));
}
集合其它操作
@Test
public void randomGetFromSet() {
long effected = j.sadd("setA", "1", "2", "3");
assertEquals(3L, effected);
String value = j.srandmember("setA");
assertTrue(value.equals("1") || value.equals("2") || value.equals("3"));
List<String> setA = j.srandmember("setA", 2);
assertEquals(2, setA.size());
String sPop = j.spop("setA");
assertNotNull(sPop);
long size = j.scard("setA");
assertEquals(2L, size);
}
实践
文章标签
一篇文章的所有标签都是互不相同的,而且展示时没有顺序,所以我们可以使用集合来存储文章的标签;
同样的,有时我们希望通过文章标签来找到文章,如果通过检索所有文章的标签来捡出指定标签的文章似乎有些太低效了,因为我们也可以创建标签的 key,然后在这个 key 下面存储不同的值。最后的示意图大致是这样的:
如果想要获取对应已经发布的指定标签的文章的 ID 只需要查看 tag 标签对应的已经发布的文章集合就可以了,如果想要查看拥有多个标签的文章只需要求交集即可。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。