第一章(二) - Dictory 底层源码剖析

提示:个人学习总结,如有错误,敬请指正。


文章目录

  • 第一章(二) - Dictory 底层源码剖析
  • 一.Dictory
    • 1.底层数据结构
    • 2.Add - 添加数据
    • 3.Remove- 删除数据
    • 4.其他接口
    • 5.Hash函数的创建过程
    • 6.线程安全
    • 7.总结
  • 附录

一.Dictory

1.底层数据结构

Key和Value用一个Hash函数来建立映射关系,处理Hash哈希冲突的方法在数据结构中会有详细讲解

Dictionary 是以数组为底层数据结构的类。当我们实例化 new Dictionary() 后,内部的数组是0个数组的状态。与 List 组件一样,Dictionary 也是需要扩容的,会随着元素数量的增加而不断扩容。


2.Add - 添加数据

Add 接口就是 Insert 的代理

返回一个size需要的最小质数值,首次定义为3每次扩容两倍-即3->7->17->37(每次都是质数)

int size = HashHelpers.GetPrime(capacity);

对Hash地址执行余数操作确保再数组长度方范围内不溢出。

    int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;int targetBucket = hashCode % buckets.Length;

指定数组单元格内的链表元素做遍历操作,找出空出来的位置将值填入;
若数组大小不够则需要再次扩容


3.Remove- 删除数据

  • 用哈希函数 comparer.GetHashCode 再除余后得到范围内的地址索引,再做余操作确定地址落在数组范围内,从哈希索引地址开始,查找冲突的元素的Key是否与需要移除的Key值相同,相同则进行移除操作并退出。
  • Remove并没有对内存进行删减,而是将对应hash位置置为默认值,这是为了减少内存的频繁操作。

4.其他接口

  • ContainsKey :

    • 与之前类似,FindEntry使用和前面相同的方式查找key的hash位置,然后从链表里匹配元素,成功返回该索引地址。
  • TryGetValue :
    • 与 ContainsKey 同样,他调用的也是FindEntry的接口,来获取Key对应的Value值。

5.Hash函数的创建过程

哈希冲突的拉链法贯穿了整个底层数据结构。因此哈希函数是关键了,哈希函数的好坏直接决定了效率高低。

    if (t == typeof(byte)) {return (EqualityComparer<T>)(object)(new ByteEqualityComparer());}// If T implements IEquatable<T> return a GenericEqualityComparer<T>if (typeof(IEquatable<T>).IsAssignableFrom(t)) {return (EqualityComparer<T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(GenericEqualityComparer<int>), t);}// If T is a Nullable<U> where U implements IEquatable<U> return a NullableEqualityComparer<U>if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>)) {RuntimeType u = (RuntimeType)t.GetGenericArguments()[0];if (typeof(IEquatable<>).MakeGenericType(u).IsAssignableFrom(u)) {return (EqualityComparer<T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(NullableEqualityComparer<int>), u);}}

对于数字类型,他们实现了IEquatable接口,直接使用GenericEqualityComparer获得hash函数。否则如果实现了Nullable接口,则调用NullableEquality-Comparer(),如果不是以上两种情况则调用ObjectEqualityComparer。


6.线程安全

和List一样,Dictionary并不是线程安全的
Hashtable在多线程读/写中是线程安全的,而Dictionary不是。如果要在多个线程中共享Dictionary的读/写操作,就要自己写lock,以保证线程安全。


7.总结

  • 从效率上看,同List一样最好在 实例化对象时,即 new 时尽量确定大致数量会更加高效,另外用数值方式做Key比用类实例方式作为Key值更加高效率
  • 从内存操作上看,大小以3->7->17->37->….的速度,每次增加2倍多的顺序进行,删除时,并不缩减内存
  • 如果想在多线程中,共享 Dictionary 则需要进行我们自己进行lock操作。
  • 减少Dictionary的冗余访问
 if(Dic.Contains(key)){var result = Dic[key];}//改写成value result ;if(Dic.TryGetValue(key,out result)){//}

附录

主程手记

【Unity主程手记(摘录)】第一章(二) - Dictory 底层源码剖析相关推荐

  1. C#要点技术(二) - Dictionary 底层源码剖析

    Dictionary 底层代码 我们知道 Dictionary 字典型数据结构,是以关键字Key 和 值Value 进行一一映射的.Key的类型并没有做任何的限制,可以是整数,也可以是的字符串,甚至可 ...

  2. LightSun/android-databinding(第一篇属性绑定)源码剖析与思考

    自从谷歌推出DataBinding框架之后,MVVM开发模式也在android的端慢慢的兴起,用DataBinding框架可以省去UI和数据绑定的不少功夫,通俗的讲就是少写很多代码,并且结构看起来清晰 ...

  3. 【Unity主程手记学习】第一章——软件架构

    架构无处不在,它实质上就是解决生活和工作中问题的一种方式.. 如果把软件比作书,那么软件架构就是书架. 一.架构的好坏由五个因素决定: 1.承载力 能承载多少逻辑系统,能承载多少个程序员同时开发,访问 ...

  4. Nacos源码系列——第一章(Nacos核心源码主线剖析上)

    在讲具体的源码之前,我有几点想说明下,很多开发可能觉得源码不重要,甚至觉得互联网 的知识,目前够用就可以,也不需要多么精通.的确,在大多数的公司中,你能用你的知识 解决问题就可以,不一定非要涉及到源码 ...

  5. 二、Neo4j源码研究系列 - 单步调试

    二.Neo4j源码研究系列 - 单步调试 一.背景介绍 上一篇我们已经把了neo4j的源码准备以及打包流程完成了,本篇将讲解如何对neo4j进行单步调试.对于不了解如何编译打包neo4j的读者,请阅读 ...

  6. 老李推荐:第5章5节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 获取系统服务引用 1...

    老李推荐:第5章5节<MonkeyRunner源码剖析>Monkey原理分析-启动运行: 获取系统服务引用 上一节我们描述了monkey的命令处理入口函数run是如何调用optionPro ...

  7. 老李推荐:第3章3节《MonkeyRunner源码剖析》脚本编写示例: MonkeyImage API使用示例 1...

    老李推荐:第3章3节<MonkeyRunner源码剖析>脚本编写示例: MonkeyImage API使用示例 在上一节的第一个"增加日记"的示例中,我们并没有看到日记 ...

  8. 老李推荐: 第8章4节《MonkeyRunner源码剖析》MonkeyRunner启动运行过程-启动AndroidDebugBridge 1...

    老李推荐: 第8章4节<MonkeyRunner源码剖析>MonkeyRunner启动运行过程-启动AndroidDebugBridge 上一节我们看到在启动AndroidDebugBri ...

  9. idea 线程内存_Java线程池系列之-Java线程池底层源码分析系列(二)

    课程简介: 课程目标:通过本课程学习,深入理解Java线程池,提升自身技术能力与价值. 适用人群:具有Java多线程基础的人群,希望深入理解线程池底层原理的人群. 课程概述:多线程的异步执行方式,虽然 ...

最新文章

  1. 服务器信息采集协议,服务器信息采集
  2. 这家公司不要求996,但照样市值万亿!
  3. c 程序 实现一元二次方程
  4. pandas 聚合函数
  5. 在一个工程(包)下面让activity和SensorEventListener监听分离,在不同类中完成
  6. 笔记本html外接显示器,笔记本如何外接显示器
  7. java标识符的介绍_Java标识符所有关键字
  8. NOI2018网络同步赛爆零记
  9. python根据url链接下载文件
  10. inside MPQ
  11. Primitive Function 归一化方向角
  12. 关于弱电间和机房的综合布线
  13. VM options常用设置
  14. 非真,亦非假——20世纪数学悖论入侵机器学习
  15. 用户画像标签系统体系解释
  16. 【python作品分享】计算器1.0
  17. 使用Element的 InfiniteScroll 无限滚动组件报错
  18. iptables企业面试题集锦
  19. 形象设计专业AR虚拟仿真实训方案
  20. OpenAI发布通用人工智能路线图:AGI比想象中来得更快

热门文章

  1. 【中医养生门户网】注意!春分在于“生、升”,保肝促阳为重
  2. 机翻福音-多种语言平行语料库资源
  3. QEMU imx6ul开发板环境搭建
  4. Automatically manage signing
  5. 学习云计算前景如何?云计算成为获取人工智能主要途径
  6. Multi-Gigabit MediaConverter车载以太网-万兆转换器
  7. 贝叶斯法则的一个例题
  8. 平方和立方和公式推导
  9. 产业区块链一周动态丨江西将出台区块链五年计划,数字货币试点引发A股躁动...
  10. JQuery制作手风琴效果