https://www.cnblogs.com/yinrq/p/5584885.html
一、HashTable
HashTable表示键/值对的集合。在.NET Framework中,Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似key-value的键值对,其中key通常可用来快速查找,同时key是区分大小写;value用于存储对应于key的值。Hashtable中key-value键值对均为object类型,所以Hashtable可以支持任何类型的keyvalue键值对,任何非 null 对象都可以用作键或值。
HashTable是一种散列表,他内部维护很多对Key-Value键值对,其还有一个类似索引的值叫做散列值(HashCode),它是根据GetHashCode方法对Key通过一定算法获取得到的,所有的查找操作定位操作都是基于散列值来实现找到对应的Key和Value值的。
散列函数(GetHashCode)让散列值对应HashTable的空间地址尽量不重复。
当一个HashTable被占用一大半的时候我们通过计算散列值取得的地址值可能会重复指向同一地址,这就造成哈希冲突。
C#中键值对在HashTable中的位置Position= (HashCode& 0x7FFFFFFF) % HashTable.Length,C#是通过探测法解决哈希冲突的,当通过散列值取得的位置Postion以及被占用的时候,就会增加一个位移x值判断下一个位置Postion+x是否被占用,如果仍然被占用就继续往下位移x判断Position+2*x位置是否被占用,如果没有被占用则将值放入其中。当HashTable中的可用空间越来越小时,则获取得到可用空间的难度越来越大,消耗的时间就越多。
HashTable使用场景:
. 什么情况下使用哈希表
(1)某些数据会被高频率查询
(2)数据量大
(3)查询字段包含字符串类型
(4)数据类型不唯一
由于 Hashtable 和 Dictionary 同时存在, 在使用场景上必然存在选择性, 并不任何时刻都能相互替代.
[1] 单线程程序中推荐使用 Dictionary, 有泛型优势, 且读取速度较快, 容量利用更充分.
[2] 多线程程序中推荐使用 Hashtable, 默认的 Hashtable 允许单线程写入, 多线程读取, 对 Hashtable 进一步调用 Synchronized() 方法可以获得完全线程安全的类型. 而 Dictionary 非线程安全, 必须人为使用 lock 语句进行保护, 效率大减.
[3] Dictionary 有按插入顺序排列数据的特性 (注: 但当调用 Remove() 删除过节点后顺序被打乱), 因此在需要体现顺序的情境中使用 Dictionary 能获得一定方便.
个人偏向于使用Dictionary,因为其使用泛型,可控性比较强。在一些资料中,很多人也推荐使用Dictionary,其原因主要有1、Dic是类型安全的,这有助于我们写出更健壮更具可读性的代码,而且省却我们强制转化的麻烦。
2、Dic是泛行的,当K或V是值类型时,其速度远远超过Hashtable。处理对象时不需要进行显式或是隐式转型,进行值类型处理时不需要装箱。所以使用方便一些,而且效率会高一些(编码效率、运行效率),还不太容易出错。摘自于: https://www.2cto.com/kf/201304/201715.html
3、如果K和V都是引用类型,如eaglet所测,Hashtable比Dic更快,这里我要指出,eaglet所做的测试是有问题的。原因在于Hashtable与Dic采用的是不同的数据结构。eaglet的“Dictionary 由于在Hashtable基础上封装了一层”这个说法是不对的。
Dictionary 调用 Add 方法之前使用 ContainsKey 方法测试某个键是否存在,否则得到一个KeyNotFoundException。
当程序频繁尝试字典中不存在的键时,使用 TryGetValue 方法来检索值,这种方法是一种更有效的检索值的方法。http://www.cnblogs.com/lucifer1982/archive/2008/06/18/1224319.html
http://www.cnblogs.com/lucifer1982/archive/2008/07/03/1234431.htmlHashtable在指定capacity参数时,它并不只开出capacity个槽的内存空间,而是开出比 capacity / 0.72(默认装填因子) 大的最小素数个槽的空间;而Dic在指定capacity时,是开出 比capacity 大的最小素数个槽的空间。因此可以看到,楼主虽然都指定capacity为10万,而实际上Hashtable的槽的总数远远大于Dic的槽的总数,也就是占用的内存远远大于Dic,因此,如此测试是不公平不公正的,如要公平公正的测试,则应该把Dic的capacity指定为 10万/0.72,请大家再测试其性能。
url:http://www.cnblogs.com/jhh0111/archive/2008/10/23/1318223.html我认为应该始终使用Dictionary<K, V>,即使要用Hashtable了,也可以用Dictionary<object, object>来替代。
关于Hashtable与Dictionary性能的讨论。:http://www.cnblogs.com/jhh0111/archive/2008/10/23/1318223.html
Dictionary 字典使用经验:
1.通过遍历获取Dictionary 的键值对时, 耗时: keys集合遍历 > keyvaluePair遍历
2.单独遍历获取Keys时, keyValPair 遍历 > values 集合遍历 用KeyValuePair反而是累赘
1. 遍历性能,如果想通过遍历获取Dictionary 的键值对,方法有两种
方法 一
/// <summary>
/// 通过key 访问键值对
/// </summary>
private static void keyPerformance(Dictionary<string,string> dic)
{
DateTime start = DateTime.Now;
string val = string.Empty;
string key = string.Empty;
foreach (string item in dic.Keys)
{
key = item;
val = dic[item];
}
DateTime end = DateTime.Now;
TimeSpan span = end.Subtract(start);
Console.WriteLine(" foreach keys spend time:{0}",span.TotalMilliseconds);
}方法 二 性能最佳 推荐使用
/// <summary>
/// 通过 KeyValuePair 访问键值对(推荐使用)
/// </summary>
/// <param name="dic"></param>
private static void keyValPerformance(Dictionary<string , string> dic)
{
DateTime start = DateTime.Now;
string val = string.Empty;
string key = string.Empty;
foreach (KeyValuePair<string ,string> item in dic)
{
key = item.Key;
val = item.Value;
}
DateTime end = DateTime.Now;
TimeSpan span = end.Subtract(start);Console.WriteLine(" foreach keyVals spend time:{0}", span.TotalMilliseconds);
}以下是耗时对比
耗时: keys集合遍历 > keyvaluePair遍历
2. 其它遍历
如果获取 dictionary 中的key 推荐 方法一
耗时: keyvalPair 遍历 >keys 集合遍历
如果获取 dictionary 中的value 推荐如下方法
private static void valPerformance(Dictionary<string , string> dic)
{
DateTime start = DateTime.Now;
string val = "";
foreach (string item in dic.Keys)
{
val = item;
}
DateTime end = DateTime.Now;
TimeSpan span = end.Subtract(start);
Console.WriteLine(" foreach vals spend time:{0}", span.TotalMilliseconds);
}
耗时: keyValPair 遍历 > values 集合遍历
数据结构~时间复杂度:http://www.cnblogs.com/lori/p/3962707.html
扩展阅读: