三 字典

  字典是Hash对象的底层实现,比如用HSET创建一个HASH的对象,底层可能就是用一个字典实现的键值对。

字典的实现主要设计下面三个结构:

/*
* 哈希表节点
*/
typedef struct dictEntry { // 键
void *key; // 值
union {
void *val;
uint64_t u64;
int64_t s64;
} v; // 指向下个哈希表节点,形成链表
struct dictEntry *next; } dictEntry; /*
* 哈希表
*
* 每个字典都使用两个哈希表,从而实现渐进式 rehash 。
*/
typedef struct dictht { // 哈希表数组
// [JZ]: 即二维数组/链表
dictEntry **table; // 哈希表大小
unsigned long size; // 哈希表大小掩码,用于计算索引值
// 总是等于 size - 1
unsigned long sizemask; // 该哈希表已有节点的数量
unsigned long used; } dictht;

/*
 * 字典类型特定函数
 */
typedef struct dictType {     // 计算哈希值的函数
    unsigned int (*hashFunction)(const void *key);     // 复制键的函数
    void *(*keyDup)(void *privdata, const void *key);     // 复制值的函数
    void *(*valDup)(void *privdata, const void *obj);     // 对比键的函数
    int (*keyCompare)(void *privdata, const void *key1, const void *key2);     // 销毁键的函数
    void (*keyDestructor)(void *privdata, void *key);
    
    // 销毁值的函数
    void (*valDestructor)(void *privdata, void *obj); } dictType; /*
* 字典
*/
typedef struct dict { // 类型特定函数
dictType *type; // 私有数据
void *privdata; // 哈希表
dictht ht[]; // rehash 索引
// 当 rehash 不在进行时,值为 -1
int rehashidx; /* rehashing not in progress if rehashidx == -1 */ // 目前正在运行的安全迭代器的数量
int iterators; /* number of iterators currently running */ } dict;

他们之间的关系如下图:

- dict.type里会注册回调函数,用来实现计算哈希值(hashFunction(),redis使用MurmurHash2算法来计算哈希值(dictEncObjHash))等等功能,用dict.sizemask计算索引值,即dictentry[i]的下标值

- 键冲突:不同的键分配到同一个索引,就在这个dictentry[i]上构成单向链表

- rehash:哈希表有一个负载因子的概念,load_factor=ht[0].used/ht[0].size,当这个值大于等于1(或者满足以下条件),会进行rehash,也代表了保存的键值过多,进行重新的散列操作,从ht[0]转移所有的hashNode到ht[1]。

rehash过程中,dict.rehashidx用来标明是否在rehash(-1为非rehash),每做一个就加1,最终全部做完后,置为-1,然后将ht[1]的所有entry拷贝回ht[0],这样不需要一次性完成所有node的rehash,避免了rehash时的庞大而集中的计算量。

rehash过程中,如果有对字典的删除,查找和更新操作,可能会对ht[0]和ht[1]都进行操作,比如查找会先到ht[0]找,找不到会到ht[1]找,如果新建,则会保存到ht[1],ht[0]不做新增,保证ht[0]里的键值对只减不增,并随着rehash最终成为空表

最新文章

  1. g++编译流程
  2. AngularJs的UI组件ui-Bootstrap分享(九)——Alert
  3. C# 编写Window服务基础(一)
  4. 多目标遗传算法 ------ NSGA-II (部分源码解析) 临时种群生成新父代种群 fillnds.c
  5. jsp分页技术
  6. 设置listview的header不能点击
  7. XStream和Json
  8. Solidity合约记录——(一)如何寻找以太坊真实Solidity源码
  9. logstash之input、codec学习
  10. 2017-2018-2 20155309 南皓芯 Exp7 网络欺诈防范
  11. net框架平台下RPC框架选型
  12. LINUX系统一一CentOS6.5之tomcat安装
  13. 带token的get和post方法
  14. VSFTPD+MYSQL+PAM
  15. element-ui Tag、Dialog组件源码分析整理笔记(五)
  16. sql查询语句示例
  17. 【转】web前端到底怎么学?干货资料!
  18. inner join和outer join
  19. [Javascript] Closure Cove, 1
  20. node、npm及node_modules中依赖的版本更新

热门文章

  1. Scala实践2
  2. Java 设置Word页边距、页面大小、页面方向、页面边框
  3. 七牛云 融合CDN测试域名 -> 融合CDN加速域名
  4. P4550 收集邮票
  5. 来自PTA Basic Level的三只小野兽
  6. 前端笔记7-js3
  7. 高校表白app使用体验
  8. 将jar包安装到本地仓库
  9. vue-DevTools安装使用
  10. mongo 查询 距离 某个点 多少 米距离 感谢 提供的数据。 感谢 mvc的 demo 。反正 就是各种感谢 文档之类的。