B.3 字典

  在框架中,字典的选择要比列表少得多。只有三个主流的非并发 IDictionary<TKey, TValue> 实现,此外还有 ExpandoObject (第14章已介绍过)、 ConcurrentDictionary (将 在介绍其他并发集合时介绍)和 RouteValueDictionary (用于路由Web请求,特别是在ASP.NET MVC中)也实现了该接口。

  注意,字典的主要目的在于为值提供有效的键查找。

B.3.1  Dictionary<TKey, TValue>

  如果没有特殊需求, Dictionary<TKey, TValue> 将是字典的默认选择,就像 List<T> 是 列表的默认实现一样。它使用了散列表,可以实现有效的查找(参见http://mng.bz/qTdH),虽然 这意味着字典的效率取决于散列函数的优劣。可使用默认的散列和相等函数(调用键对象本身的 Equals 和 GetHashCode ),也可以在构造函数中指定 IEqualityComparer<TKey> 作为参数。 最简单的示例是用不区分大小写的字符串键实现字典,如代码清单B-1所示。

            var comparer = StringComparer.OrdinalIgnoreCase;
            var dict = new Dictionary<string, int>(comparer);
            dict["Test"] = 10;
            Console.WriteLine(dict["Test"]);

  尽管字典中的键必须唯一,但散列码并不需要如此。两个不等的键完全有可能拥有相同的散 列码;这就是散列冲突(hash collision) ① ,尽管这多少会降低字典的效率,但却可以正常工作。 如果键是易变的,并且散列码在插入后发生了改变,字典将会失败。易变的字典键总是一个坏主 意,但如果确实不得不使用,则应确保在插入后不会改变。

  散列表的实现细节是没有规定的,可能会随时改变,但一个重要的方面可能会引起混淆:尽 管 Dictionary<TKey, TValue> 有时可能会按顺序排列,但无法保证总是这样。如果向字典添加 了若干项然后迭代,你会发现项的顺序与插入时相同,但请不要信以为真。有点不幸的是,刻意 添加条目以维持排序的实现可能会很怪异,而碰巧自然扰乱了排序的实现则可能带来更少的混淆。

  与 List<T> 一样, Dictionary<TKey, TValue> 将条目保存在数组中,并在必要的时候进 行扩充,且扩充的平摊复杂度为O(1)。如果散列合理,通过键访问的复杂度也为O(1);而如果所 有键的散列码都相等,由于要依次检查各个键是否相等,因此最终的复杂度为O(n)。在大多数实 际场合中,这都不是问题。

B.3.2  SortedList<TKey, TValue> 和 SortedDictionary<TKey, TValue>

  乍一看可能会以为名为 SortedList<,> 的类为列表,但实则不然。这两个类型都是字典, 并且谁也没有实现 IList<T> 。如果取名为 ListBackedSortedDictionary 和 TreeBacked- SortedDictionary 可能更加贴切,但现在改已经来不及了。

  这两个 类有很多共 同点:比较 键时都使用 IComparer<TKey> 而 不是 IEquality- Comparer<TKey> ,并且键是根据比较器排好序的。在查找值时,它们的性能均为O(log n),并 且都能执行二进制搜索。但它们的内部数据结构却迥然不同: SortedList<,> 维护一个排序的 条 目 数 组 , 而 SortedDictionary<,> 则 使 用 的 是 红 黑 树 结 构 ( 参 见 维 基 百 科 条 目 http://mng.bz/K1S4)。这导致了插入和移除时间以及内存效率上的显著差异。如果要创建一个排 序的字典, SortedList<,> 将被有效地填充,想象一下保持 List<T> 排序的步骤,你会发现向 列表末尾添加单项是廉价的(若忽略数组扩充的话将为O(1)),而随机添加项则是昂贵的,因为 涉及复制已有项(最糟糕的情况是O(n))。向 SortedDictionary<,> 中的平衡树添加项总是相 当廉价(复杂度为O(log n)),但在堆上会为每个条目分配一个树节点,这将使开销和内存碎片比 使用 SortedList<,> 键值条目的数组要更多。

  这两种集合都使用单独的集合公开键和值,并且这两种情况下返回的集合都是活动的,因为 它们将随着基础字典的改变而改变。但 SortedList<,> 公开的集合实现了 IList<T> ,因此可以 使用排序的键索引有效地访问条目。

  我不想因为谈论了这么多关于复杂度的内容而给你造成太大困扰。如果不是海量数据,则可 不必担心所使用的实现。如果字典的条目数可能会很大,你应该仔细分析这两种集合的性能特点, 然后决定使用哪一个。

B.3.3  ReadOnlyDictionary<TKey, TValue>

  熟悉了B.2.5节中介绍的 withReadOnlyCollection<T> 后, ReadOnlyDictionary<TKey, TValue> 应该也不会让你感到特别意外。 ReadOnlyDictionary<TKey, TValue> 也只是一个 围绕已有集合(本例中指 IDictionary<TKey, TValue> )的包装器而已,可隐藏显式接口实 现后所有发生变化的操作,并且在调用时抛出 NotSupportedException 。

  与只读列表相同, ReadOnlyDictionary<TKey, TValue> 的确只是一个包装器;如果基 础集合(传入构造函数的集合)发生变化,则这些修改内容可通过包装器显现出来。

原文地址:https://www.cnblogs.com/kikyoqiang/p/10187350.html

时间: 2024-10-21 14:53:10

B.3 字典的相关文章

python--15 字典:当索引不好用

字典是python唯一的影射类型 hash >>> brand = ['李宁', '耐克', '阿迪达斯'] >>> slogan = ['一切皆有可能', 'Just do it','Impossible is nothing'] >>> print('李宁的口号是:',slogan[brand.index('李宁')]) 李宁的口号是: 一切皆有可能 字典不是序列类型 ,是映射类型 字符串 列表 元组是序列类型 创建和访问索引   标志性符号--花

如何通过字典表来获取下拉数据的实现

①在web.xml中添加监听,启动的时候初始化. <!--Web ApplicationContext 载入,继承处Spring的ApplicationContextListener --> <listener> <listener-class>cn.sccl.common.web.StartupListener</listener-class> </listener> ②我们需要在启动Tomcat的时候,初始化bizCode数据 package

字典及其方法

常用操作: 索引 get,has_key, 新增 setdefalt,update, 删除 pop,popitem,clear 键.值.键值对 items,values,values 循环  for i in info: print(i,info[i])for k,v in info.items(): print(k,v) 长度 len 字典方法 dic.clear() #删除字典中所有项 dic.copy() #复制列表中所有项 dic.fromkeys(S[,v]) #新建字典,键为S,值为

SQL Server2005+、MySQL、Oracle 数据库字典生成工具

之前找的数据库字典生成工具基本上都依赖于 Office Com 组件,在不安装 Office的情况下无法使用.怒,于是自己用C# 写了一个. 特征如下:    一.支持的数据库 MS SQL Server 2005+.My Sql.Oracle    二.支持的文档类型 Html.CHM.Docx    三.无需安装Office即可生成 Docx 格式的Word文件    四.基于 .net framework 3.5 框架,电脑上需要安装 .net framework 3.5.       

python基础:python循环、三元运算、字典、文件操作

目录: python循环 三元运算 字符串 字典 文件操作基础 一.python编程 在面向过程式编程语言的执行流程中包含: 顺序执行 选择执行 循环执行 if是条件判断语句:if的执行流程属于选择执行:if语句有三种格式,如下: 在多分支的if表达式中,即使多个条件同时为真,也只会执行一个,首先测试为真: 选择执行 单分支的if语句 if CONDITION: 条件为真分支 双分支的if语句 if CONDITION 条件为真分支 else 条件不满足时分支 多分支的if语句 if CONDI

按照字典排序

按照字典排序, 按照字典的value排序,类似sort -k命令 import operator x = {1:2,3:4, 4:3, 2:1, 0:0} sorted x =sorted(x.iteritems(), key = operator.itemgetter(1)) 0表示根据key排序,1表示根据value排序 In [33]: sorted(x.iteritems(),key=operator.itemgetter(0))                             

hdu 1251 统计难题(字典树)

Problem Description Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀). Input 输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串. 注意:本题只有一组测试数据,处理到文件结束. Output 对于每个提

bing的简单英文字典工具

今天看到园友心白水撰写的<简单翻译工具--必应字典第三方API使用方法>,感觉很不错,所以用Python也写了一个.源码如下: 1 import urllib.request 2 import json 3 4 serviceurl='http://xtk.azurewebsites.net/BingDictService.aspx?Word=' 5 6 while True: 7 word = input('请输入英文单词: ') 8 if len(word) < 1 : 9 brea

无线安全专题_破解篇03--打造个人字典

上一篇讲解了如何通过Kali破解Pin码,今天继续无线安全专题破解篇的第三讲:打造个人字典.通过第一课,我们知道想要破解WPA加密,需要一个强大的字典.字典的强大直接决定了破解的可能性,废话不多说,咱们就学习一下怎么使用kali中的工具生打造个人字典.  一.crunsh工具介绍 今天主要说的是crunsh这款工具,专门用来生成字典. 命令参数: -b              #体积大小,比如-b 20mib 或者 -b 20kib -c              #密码个数(行数),比如80

json字符串和字典类型的相互转换

在开发过程中,有时候需要将json字符串转为字典类型,反之亦然,通常采用.Net的开源类库Newtonsoft.Json进行序列化,这里我也是采用这个,不过我更喜欢写扩展方法方便在项目的调用. 首先新建一个扩展类JsonExtensions(类名自己按照自己喜好定义): public static class JsonExtensions { /// <summary> /// 将字典类型序列化为json字符串 /// </summary> /// <typeparam na