转载:http://www.cnblogs.com/chengxingliang/archive/2013/04/15/3020428.html

在本文中将从基础角度讲解HashTable、Dictionary的构造和通过程序进行插入读取对比。

一:HashTable

1.HashTable是一种散列表,他内部维护很多对Key-Value键值对,其还有一个类似索引的值叫做散列值(HashCode),它是根据GetHashCode方法对Key通过一定算法获取得到的,所有的查找操作定位操作都是基于散列值来实现找到对应的Key和Value值的。

2.我们需要使用一个算法让散列值对应HashTable的空间地址尽量不重复,这就是散列函数(GetHashCode)需要做的事。

3.当一个HashTable被占用一大半的时候我们通过计算散列值取得的地址值可能会重复指向同一地址,这就是哈希冲突。

在.Net中键值对在HashTable中的位置Position= (HashCode& 0x7FFFFFFF) % HashTable.Length,.net中是通过探测法解决哈希冲突的,当通过散列值取得的位置Postion以及被占用的时候,就会增加一个位移x值判断下一个位置Postion+x是否被占用,如果仍然被占用就继续往下位移x判断Position+2*x位置是否被占用,如果没有被占用则将值放入其中。当HashTable中的可用空间越来越小时,则获取得到可用空间的难度越来越大,消耗的时间就越多。

4.当前HashTable中的被占用空间达到一个百分比的时候就将该空间自动扩容,在.net中这个百分比是72%,也叫.net中HashTable的填充因子为0.72。例如有一个HashTable的空间大小是100,当它需要添加第73个值的时候将会扩容此HashTable.

5.这个自动扩容的大小是多少呢?答案是当前空间大小的两倍最接近的素数,例如当前HashTable所占空间为素数71,如果扩容,则扩容大小为素数131.

二:Dictionary

1.Dictionary是一种变种的HashTable,它采用一种分离链接散列表的数据结构来解决哈希冲突的问题。

2.分离链接散列表是当散列到同一个地址的值存为一个链表中。

3.这个变种HashTable的填充因子是1

三:本文将以代码的形式探索HashTable和Dictionary的插入和三种读取方式的效率(for/foreach/GetEnumerator)

    public class HashTableTest
{
static Hashtable _Hashtable;
static Dictionary<string, object> _Dictionary;
static void Main()
{
Compare(10);
Compare(10000);
Compare(5000000);
Console.ReadLine();
}
public static void Compare(int dataCount)
{
Console.WriteLine("-------------------------------------------------\n");
_Hashtable = new Hashtable();
_Dictionary = new Dictionary<string, object>();
Stopwatch stopWatch = new Stopwatch();
//HashTable插入dataCount条数据需要时间
stopWatch.Start();
for (int i = 0; i < dataCount; i++)
{
_Hashtable.Add("Str" + i.ToString(), "Value");
}
stopWatch.Stop();
Console.WriteLine(" HashTable插入" + dataCount + "条数据需要时间:" + stopWatch.Elapsed); //Dictionary插入dataCount条数据需要时间
stopWatch.Reset();
stopWatch.Start();
for (int i = 0; i < dataCount; i++)
{
_Dictionary.Add("Str" + i.ToString(), "Value");
}
stopWatch.Stop();
Console.WriteLine(" Dictionary插入" + dataCount + "条数据需要时间:" + stopWatch.Elapsed); //Dictionary插入dataCount条数据需要时间
stopWatch.Reset();
int si = 0;
stopWatch.Start();
for(int i=0;i<_Hashtable.Count;i++)
{
si++;
}
stopWatch.Stop();
Console.WriteLine(" HashTable遍历时间:" + stopWatch.Elapsed + " ,遍历采用for方式"); //Dictionary插入dataCount条数据需要时间
stopWatch.Reset();
si = 0;
stopWatch.Start();
foreach (var s in _Hashtable)
{
si++;
}
stopWatch.Stop();
Console.WriteLine(" HashTable遍历时间:" + stopWatch.Elapsed + " ,遍历采用foreach方式"); //Dictionary插入dataCount条数据需要时间
stopWatch.Reset();
si = 0;
stopWatch.Start();
IDictionaryEnumerator _hashEnum = _Hashtable.GetEnumerator();
while (_hashEnum.MoveNext())
{
si++;
}
stopWatch.Stop();
Console.WriteLine(" HashTable遍历时间:" + stopWatch.Elapsed + " ,遍历采用HashTable.GetEnumerator()方式"); //Dictionary插入dataCount条数据需要时间
stopWatch.Reset();
si = 0;
stopWatch.Start();
for(int i=0;i<_Dictionary.Count;i++)
{
si++;
}
stopWatch.Stop();
Console.WriteLine(" Dictionary遍历时间:" + stopWatch.Elapsed + " ,遍历采用for方式"); //Dictionary插入dataCount条数据需要时间
stopWatch.Reset();
si = 0;
stopWatch.Start();
foreach (var s in _Dictionary)
{
si++;
}
stopWatch.Stop();
Console.WriteLine(" Dictionary遍历时间:" + stopWatch.Elapsed + " ,遍历采用foreach方式"); //Dictionary插入dataCount条数据需要时间
stopWatch.Reset();
si = 0;
stopWatch.Start();
_hashEnum = _Dictionary.GetEnumerator();
while (_hashEnum.MoveNext())
{
si++;
}
stopWatch.Stop();
Console.WriteLine(" Dictionary遍历时间:" + stopWatch.Elapsed + " ,遍历采用Dictionary.GetEnumerator()方式"); Console.WriteLine("\n-------------------------------------------------");
}
}

四:从上面的结果可以看出

1.HashTable大数据量插入数据时需要花费比Dictionary大的多的时间。

2.for方式遍历HashTable和Dictionary速度最快。

3.在foreach方式遍历时Dictionary遍历速度更快。

五:在单线程的时候使用Dictionary更好一些,多线程的时候使用HashTable更好。

因为HashTable可以通过Hashtable tab = Hashtable.Synchronized(new Hashtable());获得线程安全的对象。

当然因为各自电脑的情况不一样,可能会有部分误差。如有问题,敬请斧正。

C#中Hashtable、Dictionary详解以及写入和读取对比的更多相关文章

  1. 1、C#中Hashtable、Dictionary详解以及写入和读取对比

    在本文中将从基础角度讲解HashTable.Dictionary的构造和通过程序进行插入读取对比. 一:HashTable 1.HashTable是一种散列表,他内部维护很多对Key-Value键值对 ...

  2. oracle中imp命令详解 .

    转自http://www.cnblogs.com/songdavid/articles/2435439.html oracle中imp命令详解 Oracle的导入实用程序(Import utility ...

  3. Liunx中fstab文件详解

    Liunx中fstab文件详解 /etc/fstab是用来存放文件系统的静态信息的文件.位于/etc/目录下,可以用命令less /etc/fstab 来查看,如果要修改的话,则用命令 vi /etc ...

  4. 「翻译」Unity中的AssetBundle详解(一)

    AssetBundles AssetBundle是一个存档文件,其中包含平台在运行时加载的特定资产(模型,纹理,预制,音频剪辑,甚至整个场景).AssetBundles可以表示彼此之间的依赖关系;例如 ...

  5. ALSA声卡驱动中的DAPM详解之六:精髓所在,牵一发而动全身

    设计dapm的主要目的之一,就是希望声卡上的各种部件的电源按需分配,需要的就上电,不需要的就下电,使得整个音频系统总是处于最小的耗电状态,最主要的就是,这一切对用户空间的应用程序是透明的,也就是说,用 ...

  6. php中关于引用(&)详解

    php中关于引用(&)详解 php的引用(就是在变量或者函数.对象等前面加上&符号) 在PHP 中引用的意思是:不同的变量名访问同一个变量内容. 与C语言中的指针是有差别的.C语言中的 ...

  7. JavaScript正则表达式详解(二)JavaScript中正则表达式函数详解

    二.JavaScript中正则表达式函数详解(exec, test, match, replace, search, split) 1.使用正则表达式的方法去匹配查找字符串 1.1. exec方法详解 ...

  8. AngularJS select中ngOptions用法详解

    AngularJS select中ngOptions用法详解   一.用法 ngOption针对不同类型的数据源有不同的用法,主要体现在数组和对象上. 数组: label for value in a ...

  9. 【转载】C/C++中extern关键字详解

    1 基本解释:extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义.此外extern也可用来进行链接指定. 也就是说extern ...

随机推荐

  1. Unity3D之资源问题处理

    你做的东西如果是100%完整版 你就用 流媒体资源 Streaming Assets http://game.ceeger.com/Manual/StreamingAssets.html 你如果是类微 ...

  2. The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later.

    The server is temporarily unable to service your request due to maintenance downtime or capacity pro ...

  3. DBcontext应用于已存在数据库

    转自:http://www.cnblogs.com/Tally/archive/2013/01/30/2882855.html EF4.1有三种方式来进行数据操作及持久化.分别是Database-Fi ...

  4. java基础(二十一)IO流(四)

    这里有我之前上课总结的一些知识点以及代码大部分是老师讲的笔记 个人认为是非常好的,,也是比较经典的内容,真诚的希望这些对于那些想学习的人有所帮助! 由于代码是分模块的上传非常的不便.也比较多,讲的也是 ...

  5. [NOIP2007]奖学金

      题目来源:http://www.luogu.org/problem/show?pid=1093# 2007年NOIP全国联赛普及组 [题目描述 Description] 某小学最近得到了一笔赞助, ...

  6. rtsp的东西

    http://ubuntuforums.org/showthread.php?t=1544946 http://www.live555.com/liveCaster/liveInput.html ht ...

  7. 编译 Spring-framework的经验分享

    Spring-framework source codegit url: git clone git://github.com/SpringSource/spring-framework.git 导入 ...

  8. jvm参数设置大全

    转自:http://blog.csdn.net/kthq/article/details/8618052 参数说明 -Xmx3550m:设置JVM最大堆内存为3550M. -Xms3550m:设置JV ...

  9. Hibernate查询之HQL查询

    转自:http://blog.csdn.net/xiao_yi/article/details/1733342 Criteria查询对查询条件进行了面向对象封装,符合编程人员的思维方式,不过HQL(H ...

  10. JAVA-应用easyui

    easyui下载地址:http://www.jeasyui.com/index.php 现在还easyui之后将其解压,解压之后将文件夹中的文件除了demo文件夹之外的文件放入到Eclipse的web ...