dict:filter()可以通过传入一个断言作为参数,来对目标dict达到筛选的目的。

filter(F, D) -> filter_dict(F, D).filter_dict(F, #dict{size=0} = Dict) when is_function(F, 2) ->Dict;
filter_dict(F, D) ->Segs0 = tuple_to_list(D#dict.segs),{Segs1,Fc} = filter_seg_list(F, Segs0, [], 0),maybe_contract(D#dict{segs=list_to_tuple(Segs1)}, Fc).filter_seg_list(F, [Seg|Segs], Fss, Fc0) ->Bkts0 = tuple_to_list(Seg),{Bkts1,Fc1} = filter_bkt_list(F, Bkts0, [], Fc0),filter_seg_list(F, Segs, [list_to_tuple(Bkts1)|Fss], Fc1);
filter_seg_list(F, [], Fss, Fc) when is_function(F, 2) ->{lists:reverse(Fss, []),Fc}.filter_bkt_list(F, [Bkt0|Bkts], Fbs, Fc0) ->{Bkt1,Fc1} = filter_bucket(F, Bkt0, [], Fc0),filter_bkt_list(F, Bkts, [Bkt1|Fbs], Fc1);
filter_bkt_list(F, [], Fbs, Fc) when is_function(F, 2) ->{lists:reverse(Fbs),Fc}.filter_bucket(F, [?kv(Key,Val)=E|Bkt], Fb, Fc) ->case F(Key, Val) oftrue -> filter_bucket(F, Bkt, [E|Fb], Fc);false -> filter_bucket(F, Bkt, Fb, Fc+1)end;
filter_bucket(F, [], Fb, Fc) when is_function(F, 2) ->{lists:reverse(Fb),Fc}.

首先将dict的segs转化为列表,依次从最前面的seg开始过滤。

在filter_seg_list()函数中,依次将seg化为列表,从列表的最开始依次在filter_bkt_list()中选择slot,将slot数据依次在filter_bucket()中根据断言的true or false放入结果列表的最前端,或者给表示未命中数的Fc加一。

在完成了一个slot的过滤后,翻转列表以便正序。而后选在单个seg列表的下一个slot进行过滤,同样,一个seg被过滤完后,同样也会将结果进行逆序,确保结果的正序。

完成seg的过滤后选择下一个seg,过程与前者类似,但是最后结果再返回前,将结果单次seg的过滤结果转化为元组。

在完成所有结果后,将结果转化为元组作为原来的dict的segs。

但是由于过滤后dict数据的减少,需要将返回的dict进行缩容。通过maybe_contract()进行,同时传入的还有代表刚才进行过滤而减少的元素个数Fc。

maybe_contract(T, Dc) when T#dict.size - Dc < T#dict.con_size,T#dict.n > ?seg_size ->N = T#dict.n,Slot1 = N - T#dict.bso,Segs0 = T#dict.segs,B1 = get_bucket_s(Segs0, Slot1),Slot2 = N,B2 = get_bucket_s(Segs0, Slot2),Segs1 = put_bucket_s(Segs0, Slot1, B1 ++ B2),Segs2 = put_bucket_s(Segs1, Slot2, []),  %Clear the upper bucketN1 = N - 1,maybe_contract_segs(T#dict{size=T#dict.size - Dc,n=N1,exp_size=N1 * ?expand_load,con_size=N1 * ?contract_load,segs=Segs2});
maybe_contract(T, Dc) -> T#dict{size=T#dict.size - Dc}.maybe_contract_segs(T) when T#dict.n =:= T#dict.bso ->T#dict{maxn=T#dict.maxn div 2,bso=T#dict.bso div 2,segs=contract_segs(T#dict.segs)};
maybe_contract_segs(T) -> T.

如果原来dict的元素个数减去被过滤掉的个数仍旧大于需要缩容的大小con_size,那么直接减去并返回,否则准备开始扩容。

缩容的逻辑与扩容类似,只是代表当前活跃个数的N来减去偏移量bso代表Slot1,以便将最末尾的slot的数据放到Slot1所定位到的slot上,并将原本最末尾的slot的数据清空,N-1表示活跃的slot减少一个。

之后通过maybe_contract_segs()判断是否要将当前的dict的segs容量减半。

在完成缩容后,返回的dict就是过滤后的dict。

erlang的dict源码解析(2)相关推荐

  1. erlang的dict源码解析(1)

    Erlang的dict模块功能类似于java的hashmap. 通过dict:new()构建新的dict. new() ->Empty = mk_seg(?seg_size),#dict{emp ...

  2. erlang的gb_trees源码解析

    Erlang的gb_trees给出了平衡二叉树的实现. empty()函数给出了一个得到一个空的二叉树的途径. empty() ->{0, nil}. 空树作为一个含有两个成员的元组,第一个0则 ...

  3. erlang下lists模块sort(排序)方法源码解析(二)

    上接erlang下lists模块sort(排序)方法源码解析(一),到目前为止,list列表已经被分割成N个列表,而且每个列表的元素是有序的(从大到小) 下面我们重点来看看mergel和rmergel ...

  4. Redis源码解析——字典基本操作

    有了<Redis源码解析--字典结构>的基础,我们便可以对dict的实现进行展开分析.(转载请指明出于breaksoftware的csdn博客) 创建字典 一般字典创建时,都是没有数据的, ...

  5. Redis源码解析——前言

    今天开启Redis源码的阅读之旅.对于一些没有接触过开源代码分析的同学来说,可能这是一件很麻烦的事.但是我总觉得做一件事,不管有多大多难,我们首先要在战略上蔑视它,但是要在战术上重视它.除了一些高大上 ...

  6. VVeboTableView 源码解析

    原文链接:http://www.jianshu.com/p/78027a3a2c41 最近在看一些 iOS 性能优化的文章,我找到了 VVeboTableView 这个框架.严格来说这个不属于框架,而 ...

  7. python flask源码解析_用尽洪荒之力学习Flask源码

    [TOC] 一直想做源码阅读这件事,总感觉难度太高时间太少,可望不可见.最近正好时间充裕,决定试试做一下,并记录一下学习心得. 首先说明一下,本文研究的Flask版本是0.12. 首先做个小示例,在p ...

  8. Flask werkzeug 源码解析

    Flask werkzeug流程大概:执行run_simple ,实际执行为先用make_server 创建一个 BaseServer 实例,然后执行 实例的serve_forever 方法, ser ...

  9. [源码解析] 机器学习参数服务器 Paracel (1)-----总体架构

    [源码解析] 机器学习参数服务器 Paracel (1)-----总体架构 文章目录 [源码解析] 机器学习参数服务器 Paracel (1)-----总体架构 0x00 摘要 0x01使用 1.1 ...

最新文章

  1. python __reduce__魔法方法_关于python魔术方法payload:.__class__.__mro__[2].__subclasses__()[40](/etc/passwd...
  2. SQL语句一次INSERT多条记录的方法
  3. python适合做什么生意_适合Python的5大练手项目,你练了么?
  4. GPU Shader 编程基础
  5. ip route / ip rule /iptables 配置策略路由
  6. c# 两个list比较_C# for Grasshopper Day 22 学习笔记
  7. atoi java,leetcode题目8: 字符串转换整数 (atoi)(java)
  8. 【BZOJ 1202】 [HNOI2005]狡猾的商人
  9. 自然数之和(leetcode 167)
  10. 分子重构技术_4. 串珠模型重构
  11. 多人操作sqlite3数据库冲突问题解决方法
  12. php5.5 下载安装,【图片】PHP5.2、5.3、5.4、5.5、5.6的php memcache dll扩展下载和安装【洄溪吧】_百度贴吧...
  13. BMFont 字体生成工具使用
  14. PLUTO SDR入门系列之九:强大的开源软件“gnu radio”
  15. 高通GPS芯片WGR7640的驱动
  16. 溜客php0day挖掘,【漏洞预警】PHP7被发现三个0day漏洞,其中一个还
  17. [转]GNSS NMEA-0183协议解析
  18. softice使用(1)- 在VMware Workstation 中使用SoftICE zz xfocus
  19. 谷歌想要返华,但却陷入了尴尬境地
  20. vue中下载文件使用file-saver,文件错误excel无法打开

热门文章

  1. FTP下载文件中文名乱码FTP访问
  2. 解决tomcat的undeploy
  3. STL(六)——max_element和min_element
  4. SpringCache 集成 Redis,这才是优雅的缓存解决方案!
  5. 计算机专业能用ipad吗,iPad 能不能代替电脑?说说我这 3 个月的使用体验
  6. radius mysql md5_请教两个问题:关于无线局域网和Radius+MD5认证
  7. 查看一张表都有哪些用户有权限_有赞移动关于权限与审批流程的标准化
  8. FTL(FreeMarker)基础
  9. iOS--百度地图相关功能的实现
  10. 如何快速处理线上故障【转】