一. Dictionary与Hashtable

Dictionary与Hashtable都是.Net Framework中的字典类,能够根据快速查找

二者的特性大体上是相同的,有时可以把Dictionary<K,V>看做是Hashtable的泛型版本。不过Hashtable是线程安全的,Dictionary是有序的。

字典的性能取决于键类型的GetHashCode()方法的实现代码。

键类型也必须实现IEquatable<T>.Equals()方法,并且如果A.Equals(B)返回true,则A和B的GetHashCode()也必须返回相同的值。

Dictionary

  • 有泛型优势(类型安全,性能更好),对于值类型,不存在装箱和拆箱的性能损耗
  • 读取速度快(体现在单条数据上)
  • 容量利用更充分
  • 有序(遍历时输出的顺序就是加入的顺序)

Hashtable

  • 适合多线程
  • 通过静态方法Synchronize方法可获得完全线程安全的类型
  • 无序

二.List与Dictionary

List有点类似于Dictionary。二者都具有使用泛型的优点,Dictionary没有在内存中移动后续元素的性能开销。

List是在数组的基础上做的封装,遍历查询更快(数据较多时),Dictionary单条查询更快

引用某一篇文章的分析:

同样是集合,为什么性能会有这样的差距。我们要从存储结构和操作系统的原理谈起。 
首先我们清楚List<T>是对数组做了一层包装,我们在数据结构上称之为线性表,而线性表的概念是,在内存中的连续区域,除了首节点和尾节点外,每个节点都有着其唯一的前驱结点和后续节点。我们在这里关注的是连续这个概念。
而HashTable或者Dictionary,他是根据Key和Hash算法分析产生的内存地址,因此在宏观上是不连续的,虽然微软对其算法也进行了很大的优化。
由于这样的不连续,在遍历时,Dictionary必然会产生大量的内存换页操作,而List只需要进行最少的内存换页即可,这就是List和Dictionary在遍历时效率差异的根本原因。
 
6. 再谈Dictionary 
也许很多人说,既然Dictionary如此强大,那么我们为什么不用Dictionary来代替一切集合呢? 
在这里我们除了刚才的遍历问题,还要提到Dictionary的存储空间问题,在Dictionary中,除了要存储我们实际需要的Value外,还需要一个辅助变量Key,这就造成了内存空间的双重浪费。 
而且在尾部插入时,List只需要在其原有的地址基础上向后延续存储即可,而Dictionary却需要经过复杂的Hash计算,这也是性能损耗的地方。 
 
 
简单的做了下测试

using System.Collections;
using System.Collections.Generic; namespace ConsoleApp
{
class Program
{
public const int TOTAL_COUNT = ; public static void Main(string[] args)
{
ListTest();
DicTest();
HashtableTest();
ListInsertTest();
} private static void HashtableTest()
{
Hashtable ht = new Hashtable();
for (int i = ; i < TOTAL_COUNT; i++)
{
ht.Add(i, new Model { Num = i });
}
} public static void ListTest()
{
List<Model> list = new List<Model>();
for (int i = ; i < TOTAL_COUNT; i++)
{
list.Add(new Model { Num = i });
}
}
public static void ListInsertTest()
{
List<Model> list = new List<Model>();
list.Insert(, new Model { Num = });
list.Insert(, new Model { Num = });
for (int i = ; i < TOTAL_COUNT; i++)
{
list.Insert(,new Model { Num = i });
}
} public static void DicTest()
{
Dictionary<int, Model> dic = new Dictionary<int, Model>();
for (int i = ; i < TOTAL_COUNT; i++)
{
dic.Add(i, new Model { Num = i });
}
} public class Model
{
public int Num { set; get; }
}
}
}

测试代码

这个测试总共有四个插入数据方式:Hashtable.Add,Dictionary.Add,List.Add,List.Insert
字典中插入的Key都是int类型。 结果如下
 
方法中插入次数都是100W  因为实在等不下去了,就中途结束了。
不过这基本不影响分析结果,因为拖后腿的是List.Insert,在只执行了28W的情况下就已经占到了总耗时的95%。
从结果中可以看到插入效率依次是 List.Add -> Dictionary.Add -> Hashtable.Add -> List.Insert
这个结果也符合上面的分析。
 
下面在实测一下遍历

using System.Collections;
using System.Collections.Generic;
using System.Linq; namespace ConsoleApp
{
class Program
{
public const int TOTAL_COUNT = ; public static void Main(string[] args)
{
List<Model> list = new List<Model>();
for (int i = ; i < TOTAL_COUNT; i++)
{
list.Add(new Model { Num = i });
} Hashtable ht = new Hashtable();
for (int i = ; i < TOTAL_COUNT; i++)
{
ht.Add(i,new Model { Num = i });
} Dictionary<int, Model> dic = list.ToDictionary(l=>l.Num); ListTest(list);
DicTest(dic);
HashtableTest(ht);
} private static void HashtableTest(Hashtable ht)
{
foreach (var key in ht.Keys)
{
var rst = ht[key];
}
} public static void ListTest(List<Model> list)
{
foreach (var item in list)
{
var rst = item;
}
} public static void DicTest(Dictionary<int, Model> dic)
{
foreach (var key in dic.Keys)
{
var rst = dic[key];
}
} public class Model
{
public int Num { set; get; }
}
}
}

遍历测试代码

还是100W条数据

 
List -> Dictionary -> Hashtable
 
 
 
 

C#中Dictionary,Hashtable,List的比较及分析的更多相关文章

  1. C#中Dictionary、ArrayList、Hashtable和Array的区别

    IDictionary接口是所有字典类集合的基本接口,该接口与ICollection,IEnumerable接口是所有非泛型类集合的最基本的接口 IEnumerable接口用于公开枚举数,该枚举数支持 ...

  2. .NET中Dictionary<TKey, TValue>浅析

    .NET中Dictionary<TKey, Tvalue>是非常常用的key-value的数据结构,也就是其实就是传说中的哈希表..NET中还有一个叫做Hashtable的类型,两个类型都 ...

  3. 【C# 集合】HashTable .net core 中的Hashtable的实现原理

    上一篇我介绍了Hash函数 这篇我来说一下Hash函数在 HashTable中的应用. HashTable的特性: 1.装载因子:.net core 0.72 ,java 0.75 2.冲突解决方案: ...

  4. C#中Dictionary<TKey,TValue>排序方式

    自定义类: using System; using System.Collections.Generic; using System.Linq; using System.Text; using Sy ...

  5. C#中Dictionary小记

    使用C#中Dictionary的一下细节小记: 一.Dictionary.Add(key,value) 与 Dictionary[key]=value的区别: 如果Dictionary中已经有了key ...

  6. 在webservice中传递Hashtable

    webservice中不支持hashtable的数据类型,那么如何在webservice中传递hashtable呢?我们可以通过将hashtable转化为webservice中支持的数组的类型来进行传 ...

  7. C#中Dictionary的用法

    在C#中,Dictionary提供快速的基于兼职的元素查找.他的结构是这样的:Dictionary<[key], [value]> ,当你有很多元素的时候可以使用它.它包含在System. ...

  8. ASP.NET中Dictionary基本用法实例分析

    本文实例讲述了ASP.NET中Dictionary基本用法.分享给大家供大家参考,具体如下: //Dictionary位于System.Collections.Generic命名空间之下 /*  * ...

  9. C#中Dictionary排序方式

    转载自:https://www.cnblogs.com/5696-an/p/5625142.html 自定义类: https://files.cnblogs.com/files/xunhanliu/d ...

随机推荐

  1. .Net 配置文件--继承ConfigurationSection实现自定义处理类处理自定义配置节点

    除了使用继承IConfigurationSectionHandler的方法定义处理自定义节点的类,还可以通过继承ConfigurationSection类实现同样效果. 首先说下.Net配置文件中一个 ...

  2. 【iOS】FMDB/SQLCipher数据库加解密,迁移

    2016-04-19更新:本文代码可能有些问题,请移步 http://zhengbomo.github.io/2016-04-18/sqlcipher-start/ 查看 sqlite应用几乎在所有的 ...

  3. ADO.net中常用的对象介绍

    ADO.NET的对象主要包括:DataSet,DataTable,DataColumn,DataRow,和DataRelation. DataSet:这个对象是一个集合对象,它可以包含任意数量的数据表 ...

  4. C#继承基本控件实现自定义控件

    C#继承基本控件实现自定义控件 摘自:http://www.cnblogs.com/greatverve/archive/2012/04/25/user-control-inherit.html 自定 ...

  5. python函数和常用模块(一),Day3

    set集合 函数 三元运算 lambda表达式 内置函数1 文件操作 set集合 创建 se = {"123", "456"} # 直接创建一个集合 se = ...

  6. redis 慢日志 slowlog

    1 slowlog是什么 redis的slowlog是redis用于记录记录慢查询执行时间的日志系统.由于slowlog只保存在内存中,因此slowlog的效率很高,完全不用担心会影响到redis的性 ...

  7. Vue计算属性

    github地址:https://github.com/lily1010/vue_learn/tree/master/lesson06 一 计算属性定位 当一些数据需要根据其它数据变化时,这时候就需要 ...

  8. 新技能,利用Reflector来修改dll引用

    继上次<ArcObject10.1降级至10.0>又遇到版本降级问题.通常的方式有: 方案一:重新编译 将源代码加载到解决方案中,修改相应dll的版本,比较快捷的方式是多选后,设置属性中特 ...

  9. 高清HDMI编码器|上海视涛科技

    HDMI编码器(E300)简介 HDMI编码器(E300)是上海视涛科技出品的高性能HDMI+VGA编码产品.该HDMI+VGA编码器是上海视涛科技完全自主研发,并适用于VGA.DVI.HDMI等信号 ...

  10. 对抗静态分析——运行时修复dex

    对抗静态分析——运行时修复dex   本文来源:i春秋社区-分享你的技术,为安全加点温度 零.写在前面   这个系列本来题目想写对抗反编译,可是想想对抗反编译的这个范围有点大,总结如下 灵魂作图   ...