在本文中将从基本角度讲授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()格式");