欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C# Hashtable/Dictionary寫入和讀取對比詳解

 更新時間:2013年11月20日 15:22:34   作者:  
本文中將從基礎(chǔ)角度講解HashTable、Dictionary的構(gòu)造和通過程序進(jìn)行插入讀取對比

一:HashTable
1.HashTable是一種散列表,他內(nèi)部維護(hù)很多對Key-Value鍵值對,其還有一個類似索引的值叫做散列值(HashCode),它是根據(jù)GetHashCode方法對Key通過一定算法獲取得到的,所有的查找操作定位操作都是基于散列值來實現(xiàn)找到對應(yīng)的Key和Value值的。
2.我們需要使用一個算法讓散列值對應(yīng)HashTable的空間地址盡量不重復(fù),這就是散列函數(shù)(GetHashCode)需要做的事。
3.當(dāng)一個HashTable被占用一大半的時候我們通過計算散列值取得的地址值可能會重復(fù)指向同一地址,這就是哈希沖突。
在.Net中鍵值對在HashTable中的位置Position= (HashCode& 0x7FFFFFFF) % HashTable.Length,.net中是通過探測法解決哈希沖突的,當(dāng)通過散列值取得的位置Postion以及被占用的時候,就會增加一個位移x值判斷下一個位置Postion+x是否被占用,如果仍然被占用就繼續(xù)往下位移x判斷Position+2*x位置是否被占用,如果沒有被占用則將值放入其中。當(dāng)HashTable中的可用空間越來越小時,則獲取得到可用空間的難度越來越大,消耗的時間就越多。
4.當(dāng)前HashTable中的被占用空間達(dá)到一個百分比的時候就將該空間自動擴(kuò)容,在.net中這個百分比是72%,也叫.net中HashTable的填充因子為0.72。例如有一個HashTable的空間大小是100,當(dāng)它需要添加第73個值的時候?qū)U(kuò)容此HashTable.
5.這個自動擴(kuò)容的大小是多少呢?答案是當(dāng)前空間大小的兩倍最接近的素數(shù),例如當(dāng)前HashTable所占空間為素數(shù)71,如果擴(kuò)容,則擴(kuò)容大小為素數(shù)131.

二:Dictionary

1.Dictionary是一種變種的HashTable,它采用一種分離鏈接散列表的數(shù)據(jù)結(jié)構(gòu)來解決哈希沖突的問題。
2.分離鏈接散列表是當(dāng)散列到同一個地址的值存為一個鏈表中。
3.這個變種HashTable的填充因子是1

三:本文將以代碼的形式探索HashTable和Dictionary的插入和三種讀取方式的效率(for/foreach/GetEnumerator)

復(fù)制代碼 代碼如下:

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條數(shù)據(jù)需要時間
            stopWatch.Start();
            for (int i = 0; i < dataCount; i++)
            {
                _Hashtable.Add("Str" + i.ToString(), "Value");
            }
            stopWatch.Stop();
            Console.WriteLine(" HashTable插入" + dataCount + "條數(shù)據(jù)需要時間:" + stopWatch.Elapsed);

            //Dictionary插入dataCount條數(shù)據(jù)需要時間
            stopWatch.Reset();
            stopWatch.Start();
            for (int i = 0; i < dataCount; i++)
            {
                _Dictionary.Add("Str" + i.ToString(), "Value");
            }
            stopWatch.Stop();
            Console.WriteLine(" Dictionary插入" + dataCount + "條數(shù)據(jù)需要時間:" + stopWatch.Elapsed);

            //Dictionary插入dataCount條數(shù)據(jù)需要時間
            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條數(shù)據(jù)需要時間
            stopWatch.Reset();
            si = 0;
            stopWatch.Start();
            foreach (var s in _Hashtable)
            {
                si++;
            }
            stopWatch.Stop();
            Console.WriteLine(" HashTable遍歷時間:" + stopWatch.Elapsed + " ,遍歷采用foreach方式");

            //Dictionary插入dataCount條數(shù)據(jù)需要時間
            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條數(shù)據(jù)需要時間
            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條數(shù)據(jù)需要時間
            stopWatch.Reset();
            si = 0;
            stopWatch.Start();
            foreach (var s in _Dictionary)
            {
                si++;
            }
            stopWatch.Stop();
            Console.WriteLine(" Dictionary遍歷時間:" + stopWatch.Elapsed + " ,遍歷采用foreach方式");

            //Dictionary插入dataCount條數(shù)據(jù)需要時間
            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-------------------------------------------------");
        }
    }




四:從上面的結(jié)果可以看出

1.HashTable大數(shù)據(jù)量插入數(shù)據(jù)時需要花費比Dictionary大的多的時間。
2.for方式遍歷HashTable和Dictionary速度最快。
3.在foreach方式遍歷時Dictionary遍歷速度更快。
五:在單線程的時候使用Dictionary更好一些,多線程的時候使用HashTable更好。
因為HashTable可以通過Hashtable tab = Hashtable.Synchronized(new Hashtable());獲得線程安全的對象。
當(dāng)然因為各自電腦的情況不一樣,可能會有部分誤差。如有問題,敬請斧正。

相關(guān)文章

  • C#實現(xiàn)跑馬燈效果的示例代碼

    C#實現(xiàn)跑馬燈效果的示例代碼

    跑馬燈效果,功能效果大家應(yīng)該都知道,就是當(dāng)我們的文字過長,整個頁面放不下的時候(一般用于公告等),可以讓它自動實現(xiàn)來回滾動。本文將利用C#實現(xiàn)這一效果,感興趣的可以了解一下
    2022-11-11
  • C#啟動和停止windows服務(wù)的實例代碼

    C#啟動和停止windows服務(wù)的實例代碼

    這篇文章介紹了C#啟動和停止windows服務(wù)的實例代碼,有需要的朋友可以參考一下
    2013-09-09
  • Winform項目中使用FastReport.Net報表控件

    Winform項目中使用FastReport.Net報表控件

    這篇文章介紹了Winform項目中使用FastReport.Net報表控件的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • C#創(chuàng)建控制Windows服務(wù)

    C#創(chuàng)建控制Windows服務(wù)

    這篇文章介紹了C#創(chuàng)建和控制Windows服務(wù)的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-02-02
  • C# 設(shè)計模式系列教程-橋接模式

    C# 設(shè)計模式系列教程-橋接模式

    橋接模式降低了沿著兩個或多個維度擴(kuò)展時的復(fù)雜度,防止類的過度膨脹,解除了兩個或多個維度之間的耦合,使它們沿著各自方向變化而不互相影響。
    2016-06-06
  • C#線程 BeginInvoke和EndInvoke使用方法

    C#線程 BeginInvoke和EndInvoke使用方法

    本文開始C#線程系列講座之一,即BeginInvoke和EndInvoke的使用方法,需要的朋友可以參考下
    2013-05-05
  • C#結(jié)合OpenCVSharp4使用直方圖算法實現(xiàn)圖片相似度比較

    C#結(jié)合OpenCVSharp4使用直方圖算法實現(xiàn)圖片相似度比較

    這篇文章主要為大家詳細(xì)介紹了C#如何結(jié)合OpenCVSharp4使用直方圖算法實現(xiàn)圖片相似度比較,文中的示例代碼簡潔易懂,需要的小伙伴可以參考下
    2023-09-09
  • C#如何打開并讀取usb的文件目錄

    C#如何打開并讀取usb的文件目錄

    這篇文章主要介紹了用C#語言實現(xiàn)打開并讀取usb的文件目錄,但是實現(xiàn)此功能要注意一點必須在u盤插入才能接受到信息,需要的朋友可以參考下
    2015-07-07
  • C#調(diào)用Nero SDK刻錄光盤的方法

    C#調(diào)用Nero SDK刻錄光盤的方法

    這篇文章主要介紹了C#調(diào)用Nero SDK刻錄光盤的方法,涉及C#調(diào)用NeroCOM組件實現(xiàn)光盤刻錄的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-07-07
  • 基于c# 接口的實例詳解

    基于c# 接口的實例詳解

    本篇文章是對c#中的接口進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-06-06

最新評論