REDIS_SET 集合 是SADD 、SRANDMEMBER 等命令的操作对象 它使用

REDIS_ENCODING_INTSET 和REDIS_ENCODING_HT 两种方式编码

编码的选择

第一个添加到集合的元素决定了创建集合时所使用的编码

如果第一个元素可以表示为long long 类型值也即是它是一个整数那么集合的初

始编码为REDIS_ENCODING_INTSET 。

否则集合的初始编码为REDIS_ENCODING_HT 。

编码的切换

如果一个集合使用REDIS_ENCODING_INTSET 编码那么当以下任何一个条件被满足时这个

集合会被转换成REDIS_ENCODING_HT 编码

intset 保存的整数值个数超过server.set_max_intset_entries 默认值为512 。

试图往集合里添加一个新元素并且这个元素不能被表示为long long 类型也即是

它不是一个整数。

字典编码的集合

当使用REDIS_ENCODING_HT 编码时集合将元素保存到字典的键里面而字典的值则统一设

为NULL 。

作为例子以下图片展示了一个以REDIS_ENCODING_HT 编码表示的集合集合的成员为elem1

、elem2 和elem3

集合命令的实现

Redis 集合类型命令的实现主要是对intset 和dict 两个数据结构的操作函数的包装以及

一些在两种编码之间进行转换的函数大部分都没有什么需要解释的地方唯一比较有趣的是

SINTER 、SUNION 等命令之下的算法实现以下三个小节就分别讨论它们所使用的算法。

求交集算法

SINTER 和SINTERSTORE 两个命令所使用的求并交集算法可以用Python 表示如下

# coding: utf-8
def sinter(*multi_set):
# 根据集合的基数进行排序
sorted_multi_set = sorted(multi_set, lambda x, y: len(x) - len(y))
# 使用基数最小的集合作为基础结果集有助于降低常数项
result = sorted_multi_set[0].copy()
# 剔除所有在sorted_multi_set[0] 中存在
# 但在其他某个集合中不存在的元素
for elem in sorted_multi_set[0]:
for s in sorted_multi_set[1:]:
if (not elem in s):
result.remove(elem)
break
return result

算法的复杂度为O(N2) 执行步数为S T 其中S 为输入集合中基数最小的集合而T 则

为输入集合的数量。

求并集算法

SUNION 和SUNIONSTORE 两个命令所使用的求并集算法可以用Python 表示如下

# coding: utf-8
def sunion(*multi_set):
result = set()
for s in multi_set:
for elem in s:
# 重复的元素会被自动忽略
result.add(elem)
return result

算法的复杂度为O(N) 。

求差集算法

Redis 为SDIFF 和SDIFFSTORE 两个命令准备了两种求集合差的算法。

以Python 代码表示的算法一定义如下

# coding: utf-8
def sdiff_1(*multi_set):
result = multi_set[0].copy()
sorted_multi_set = sorted(multi_set[1:], lambda x, y: len(x) - len(y))
# 当elem 存在于除multi_set[0] 之外的集合时
# 将elem 从result 中删除
for elem in multi_set[0]:
for s in sorted_multi_set:
if elem in s:
result.remove(elem)
break
return result

这个算法的复杂度为O(N2) 执行步数为S T 其中S 为输入集合中基数最小的集合而

T 则为除第一个集合之外其他集合的数量。

以Python 代码表示的算法二定于如下

# coding: utf-8
def sdiff_2(*multi_set):
# 用第一个集合作为结果集的起始值
result = multi_set[0].copy()
for s in multi_set[1:]:
for elem in s:
# 从结果集中删去其他集合中包含的元素
if elem in result:
result.remove(elem)
return result

这个算法的复杂度同样为O(N2) 执行步数为S 其中S 为所有集合的基数总和。

Redis 使用一个程序决定该使用那个求差集算法程序用Python 表示如下

# coding: utf-8
from sdiff_1 import sdiff_1
from sdiff_2 import sdiff_2
def sdiff(*multi_set):
# 算法一的常数项较低给它一点额外的优先级
algo_one_advantage = 2
algo_one_weight = len(multi_set[0]) * len(multi_set[1:]) / algo_one_advantage
algo_two_weight = sum(map(len, multi_set))
if algo_one_weight <= algo_two_weight:
return sdiff_1(*multi_set)
else:
return sdiff_2(*multi_set)

转载于:https://blog.51cto.com/janephp/1363456

Redisbook学习笔记(3)数据类型之集合相关推荐

  1. 判断题:oracle自带的sql语言环境是pl/sql,Oracle之PL/SQL学习笔记之数据类型(三)

    Oracle之PL/SQL学习笔记之数据类型(三) 所有的编程语言中变量是使用最频繁的.PL/SQL作为一个面向过程的数据库编程语言同样少不了变量,利用变量可以把PL/SQL块需要的参数传递进来,做到 ...

  2. pythonsze_python学习笔记二 数据类型(基础篇)

    Python基础 对于Python,一切事物都是对象,对象基于类创建 不同类型的类可以创造出字符串,数字,列表这样的对象,比如"koka".24.['北京', '上海', '深圳' ...

  3. C++学习笔记1[数据类型]

    C++学习目录链接: C++学习笔记目录链接(持续更新中) 文章目录 一.数据类型 1.helloworld 2.注释 3.main函数.函数体.返回值 4.常量 5.变量 6.数据的输入和输出 7. ...

  4. Redisbook学习笔记(3)数据类型之对象处理机制

    在Redis 的命令中,用于对键(key)进行处理的命令占了很大一部分,而对于键所保存的值的 类型(后简称"键的类型" ),键能执行的命令又各不相同. 比如说,LPUSH 和LLE ...

  5. Redisbook学习笔记(3)数据类型之字符串

    REDIS_STRING (字符串)是Redis 使用得最为广泛的数据类型,它除了是SET .GET 等命令 的操作对象之外,数据库中的所有键,以及执行命令时提供给Redis 的参数,都是用这种类型 ...

  6. Redisbook学习笔记(3)数据类型之列表

    REDIS_LIST (列表) 是LPUSH .LRANGE 等命令的操作对象, 它使用 REDIS_ENCODING_ZIPLIST 和REDIS_ENCODING_LINKEDLIST 这两种方式 ...

  7. arraylist如何检测某一元素是否为空_java学习笔记:【ArrayList集合】

    在介绍ArrayList集合前,我先简单的说一下什么是集合.集合,顾名思义,是很多东西聚集在一起叫集合,在java中,集合是用来储存数据的一种容器,它和之前介绍过的数组有相似之处. 它与数组的主要区别 ...

  8. javascript深入浅出——学习笔记(六种数据类型和隐式转换)

    在慕课之前学过JS深入浅出,最近发现很多东西都记不太清楚了,再复习一遍好了,感觉这个课程真的超级棒的,做做笔记,再添加一些学习内容?随时补充 课程大纲 1.数据类型 2.表达式和运算符 3.语句 4. ...

  9. JavaSE学习笔记 详解Set集合中实现类:LinkedHashSet以及TreeSet

    详解Set集合中实现类:LinkedHashSet以及TreeSet 1.LinkedHashSet概述 2.TreeSet概述 2.1 自然排序 2.1.1 TreeSet存储常见引用数据类型 2. ...

最新文章

  1. 数据结构与算法:06 线性表
  2. 解决 IDEA 使用过程中让你觉得不爽的一些问题
  3. 解决postgresql数据库localhost可以连接,ip连接不了的问题
  4. HTML5手机手写签名开发,html5手写签名
  5. UA OPTI512R 傅立叶光学导论 衍射例题
  6. 一步一步掌握设计模式一(最简单的开始--单例模式^_^)
  7. 一维傅里叶变换后的复数怎样理解?
  8. 软考信息安全必备考点
  9. 2DToolkit官方文档中文版打地鼠教程(一):初始设置
  10. IDEA--tomcat日志乱码
  11. JAVA短信验证码接口API
  12. RGB与YIQ的转换
  13. “你是个成熟的设备了,要学会保护自己”
  14. 无法删除文件,无法读源文件或磁盘
  15. 方舟服务器制作修改,方舟生存进化服务器模式设置教程
  16. windows ubuntu 双系统 蓝屏Technical information: ***stop:0x0000007B(0x80786B58,0xC0000034,0x00000000,0x00
  17. linux设置合上电脑,[转载]笔记本上装CentOS 7 设置合上盖子不休眠
  18. 纺织品行业——瑞士蓝标Bluesign认证
  19. 航海新说|掌舵绝招 -- 弹性 · 敏捷 · 开放
  20. 鼠标悬停显示滚动条,移出不显示

热门文章

  1. Kaggle 首战拿银总结 | 入门指导 (长文、干货)
  2. linux系统管理员的家目录是,最新linux网络操作系统与实训 课后习题答案汇编...
  3. html表格极细边框,html中表格细边框的四种实现及其比较
  4. 《系统集成项目管理工程师》必背100个知识点-21监控项目工作ITTO
  5. Winform中实现执行cmd命令的工具类
  6. Docker中部署Mysql8数据库
  7. Winform中通过代码设置DevExpress的TextEdit的类型为Numbernic
  8. 【LeetCode】390.消除游戏
  9. python mysql数据库长连接_python 长连接 mysql数据库
  10. php添加linux定时任务,PHP与Linux定时任务