C#中哈希表与List的比较
简单概念
在c#中,List是顺序线性表(非链表),用一组地址连续的存储单元依次存储数据元素的线性结构。
哈希表也叫散列表,是一种通过把关键码值映射到表中一个位置来访问记录的数据结构。c#中的哈希表有Hashtable,Dictionary,Hashtable继承自Map,实现一个key-value映射的关系。Dictionary则是一种泛型哈希表,不同于Hashtable的key无序,Dictionary是按照顺序存储的。哈希表的特点是:1.查找速度快,2.不能有重复的key。
创建过程
在c#中,我们实例化list时,如果不指定容量,则内部会生成一个静态的空数组,有添加操作时,实例化为一个长度为4的数组,满了以后,自动扩充为两倍的容量。
哈希表也是类似的情况,先默认生成一个长度为11的哈希表,满后,自动添加,而添加规则是内部循环素数数组,稍大于当前的长度,比如15 ,则长度设定为17。在哈希表创建可分为确定哈希函数,解决哈希冲突两个步骤。
实验执行结果
下面进行两个实验,实验一,比较Hashtable,Dictionary,List三者在不同长度时的创建速度,实验二比较三者在不同时间时的查找速度。(实验代码在最后)
硬件:intel core 2 quad cpu @ 2.66GHZ,4GB内存。
软件:windows 2008,2010 VS编译环境。
表1.三者的创建时间
长度\类型 |
Hashtable |
Dictionary |
List |
1 |
0.001s |
0s |
0s |
10 |
0S |
0S |
0s |
100 |
0S |
0S |
0s |
1000 |
0.003s |
0.005s |
0.001s |
10000 |
0.0032s |
0.003s |
0.002s |
100000 |
0.038s |
0.042s |
0.002s |
1000000 |
0.520s |
0.512s |
0.015s |
3000000 |
1.807s |
1.441s |
0.042s |
6000000 |
3.752s |
2.952s |
0.087s |
8000000 |
4.744s |
3.740s |
0.102s |
表2.三者的查找时间
长度\类型 |
Hashtable |
Dictionary |
List |
1 |
0s |
0s |
0s |
10 |
0s |
0s |
0s |
100 |
0s |
0s |
0s |
1000 |
0s |
0s |
0s |
10000 |
0s |
0s |
0.001s |
100000 |
0s |
0s |
0.010s |
1000000 |
0s |
0s |
0.009s |
3000000 |
0s |
0s |
0.009s |
6000000 |
0s |
0s |
0.058s |
8000000 |
0s |
0s |
0.077s |
总结
实验一表明:哈希表比list需要花费更多的时间建立数据结构,这是因为哈希表花费时间去解决哈希冲突,而list不需要。但需要注意的是建立操作只需要执行一次。
实验二表明:哈希表的查找速度几乎不需要花费时间,这是因为哈希表在添加一对元素(key-value)时,就已经记录下value的位置,所以查找时就会非常的快。哈希的查找复杂度O(1),list 的查找复杂度是O(n)。
哈希表的高速查找是空间换时间的典型应用,前期的建立时间随着数量级的增加而增加,后期的查找则永远是O(1)。所以我们得出结论:如果面对海量数据,且需要大量搜索,那建议使用哈希表。而当面对小量数据(数量级由服务器决定)时,使用List更合适。
最后友情提醒:第一,虽然在查找上哈希占有优势,但不足的是1.占有空间大,2.不能有重复健。第二,如果需要使用哈希表,建议多使用Dictionary。Dictionary的运行时间比hashtable稍快,而且Dictionary是类型安全的,这有助于我们写出更健壮更具可读性的代码,省去我们强制转化的麻烦。Dictionary是泛型的,当K或V是值类型时,其速度远远超过Hashtable。
- /*
- *Author: chao
- *Date:2012.3.27
- *Fun: Compare list with hash in c#
- */
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Collections;
- namespace hash_vs_list
- {
- class Program
- {
- const int MAX = 50000;
- static void Main(string[] args)
- {
- //hash_table
- Console.WriteLine("hash_table");
- TimeSpan hash_start = new TimeSpan(DateTime.Now.Ticks); //开始时间
- Hashtable h1 = new Hashtable();
- for (int i = 0; i < MAX; i++)
- h1.Add(i, i.ToString());
- TimeSpan hash_end = new TimeSpan(DateTime.Now.Ticks); //结束时间
- TimeSpan hash_diff = hash_start.Subtract(hash_end).Duration();// 计算时间差
- string hash_create_diff = hash_diff.TotalSeconds.ToString(); //
- //hashtable search
- hash_start = new TimeSpan(DateTime.Now.Ticks);
- string tmp = h1[0].ToString();
- hash_end = new TimeSpan(DateTime.Now.Ticks);
- hash_diff = hash_start.Subtract(hash_end).Duration();
- string hash_search_diff = hash_diff.TotalSeconds.ToString();
- Console.WriteLine("create:{0} search:{1}", hash_create_diff, hash_search_diff);
- Console.WriteLine();
- //dict
- Console.WriteLine("dictionary");
- Dictionary<int, string> dict = new Dictionary<int, string>();
- TimeSpan dict_start = new TimeSpan(DateTime.Now.Ticks);
- for (int i = 0; i < MAX; i++)
- {
- dict.Add(i, i.ToString());
- }
- TimeSpan dict_end = new TimeSpan(DateTime.Now.Ticks);
- TimeSpan dict_diff = dict_start.Subtract(dict_end).Duration();
- string dict_create_diff = dict_diff.TotalSeconds.ToString();
- //dict search
- dict_start = new TimeSpan(DateTime.Now.Ticks);
- tmp = dict[0];
- dict_end = new TimeSpan(DateTime.Now.Ticks);
- dict_diff = dict_start.Subtract(dict_end).Duration();
- string dict_search_diff = dict_diff.TotalSeconds.ToString();
- Console.WriteLine("create:{0} search:{1}", dict_create_diff, dict_search_diff);
- Console.WriteLine();
- //list create
- Console.WriteLine("list");
- TimeSpan list_start = new TimeSpan(DateTime.Now.Ticks);
- List<int> l1 = new List<int>();
- for (int i = 0; i < MAX; i++)
- l1.Add(i);
- TimeSpan list_end = new TimeSpan(DateTime.Now.Ticks);
- TimeSpan list_diff = list_start.Subtract(list_end).Duration();
- string list_create_diff = list_diff.TotalSeconds.ToString();
- //list foreach
- list_start = new TimeSpan(DateTime.Now.Ticks);
- foreach (int i in l1)
- {
- if (i == MAX)
- break;
- }
- list_end = new TimeSpan(DateTime.Now.Ticks);
- list_diff = list_start.Subtract(list_end).Duration();
- string list_foreach_diff = list_diff.TotalSeconds.ToString();
- Console.WriteLine("create:{0},foreach:{1}", list_create_diff, list_foreach_diff);
- Console.WriteLine();
- Console.Read();
- }
- }
- }
C#中哈希表与List的比较的更多相关文章
- js中哈希表的几种用法总结
本篇文章只要是对js中哈希表的几种用法进行了总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助 1. <html> <head> <script type=" ...
- Java中哈希表(Hashtable)是如何实现的
Java中哈希表(Hashtable)是如何实现的 Hashtable中有一个内部类Entry,用来保存单元数据,我们用来构建哈希表的每一个数据是Entry的一个实例.假设我们保存下面一组数据,第一列 ...
- [转]net中哈希表的使用 Hashtable
本文转自:http://www.cnblogs.com/gsk99/archive/2011/08/28/2155988.html 以下是PetShop中DBHelper中的使用过程: //创建哈希表 ...
- C++ STL中哈希表Map 与 hash_map 介绍
0 为什么需要hash_map 用过map吧?map提供一个很常用的功能,那就是提供key-value的存储和查找功能.例如,我要记录一个人名和相应的存储,而且随时增加,要快速查找和修改: 岳不群-华 ...
- C#中哈希表(HashTable)的用法详解以及和Dictionary比较
1. 哈希表(HashTable)简述 在.NET Framework中,Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似keyvalue的键值对, ...
- MySQL中哈希表
也称为散列表 由直接寻址表改进而来.先看直接寻址表 当关键字的全域U比较小时,直接寻址是一种简单而有效的技术.加入某应用要用到一个动态集合,其中每个元素都有一个取自全域U={0,1,...,m-1}的 ...
- 转 C#中哈希表(HashTable)的用法详解
看了一遍有关哈希表的文字,作者总结的真是不错 .收藏起来 1. 哈希表(HashTable)简述 在.NET Framework中,Hashtable是System.Collections命名空间提 ...
- C#中哈希表(HashTable)的用法详解
描述: 哈希表存放 key.values ,key值可以用于快速调取用,values 对应object类型,也就是说所有类型. 实例: 1.HashTable存放学生的成绩 Hashtable ht1 ...
- libnids 中哈希表的建立
//hash.c #include <sys/types.h>#include <sys/time.h>#include <stdio.h>#include < ...
随机推荐
- C# 学习之旅(2)--- 意外的收获
今天在完成老师布置的C#作业(计算一元二次方程的根)的时候,收获到意外的知识,所以写此博文予以记录. 意外收获为: 对文本框的输入值进行检测,使之按照要求格式输入. 下面是整个的源代码: using ...
- 2014年辛星完全解读Javascript第七节 数组和对象
由于Javascript是脚本语言,因此,使用起来非常方便,数组的使用也是比较简单的,下面我们就主要介绍一下Javascript中数组的介绍,以及上一节中没有完成的对象的介绍. *********** ...
- Mysql 备份恢复之 Mysqldump 工具
目前正在学习中,看到mysqldump工具导出的数据都是文本形式的,如果是blob或text大对象类型导出的是什么格式的?这个需要后续研究.下面只先总结下简单的. 一.备份1.备份Mysql一个数据库 ...
- 在Qt Creator中添加OpenCV库
在项目的pro文件中添加如下代码:INCLUDEPATH += D:/opencv/build/include win32:CONFIG(debug, debug|release): {LIBS += ...
- linux工作队列
工作队列一般用来做滞后的工作,比如在中断里面要做很多事,但是比较耗时,这时就可以把耗时的工作放到工作队列.说白了就是系统延时调度的一个自定义函数. 工作队列是实现延迟的新机制,从 2.5 版本 Lin ...
- SQL 跨服务器数据库增、删、改、查(一)
--开启本服务器中操作其他服务器的功能 reconfigure --输出消息 reconfigure --输出消息 --增 INSERT INTO OPENROWSET('SQLOLEDB','jx3 ...
- java接口与继承
class Grandparent { public Grandparent() { System.out.println("GrandParent Created."); } p ...
- WCF服务的创建和发布到IIS
一. WCF服务的创建 有两种创建方式: 1.WCF服务库 2.WCF服务应用程序 如下图所示: 这里选择WCF服务库.注意事项: 1.WCF服务库是一个类库项目,这里选择.net 3.5版本(版本高 ...
- js的原型链
js中的原型链是一个很重要的概念,理解了原型链,对js程序的开发有很大的好处,废话不说,先上图: javascript是基于原型的语言,所以一个对象可以另一个对象继承.不过javascript实现的时 ...
- 用IDEA调试Play工程
IDEA的版本是14.0.1,运行在MAC OS X Yosemite上. IDEA已经装了Scala插件,但是在新建工程中,Scala的选项中并没有Play框架,不知道什么原因. 导入Play工程 ...