System.Collections.Generic 原始碼閱讀總結

寂滅萬乘發表於2018-08-03

ArrayList ,List

ArrayList 和 List 都是不限制長度的集合型別 ,List相比ArrayList 就內部實現而言除了泛型本質沒有太大區別。不過為避免裝箱拆箱問題,儘可能使用List

集合內部是由陣列實現,預設大小是4,但你使用無參建構函式構造例項時,內部陣列大小是0,當你加入第一個元素時,才擴容為4,新增元素時,如果發現內建陣列大小不夠,內建陣列大小會擴容為原來的兩倍,每一次擴容都會重新開闢一個陣列,拷貝舊陣列的資料,如果你要給集合新增大量的元素卻不為它初始化一個合適容量,頻繁的記憶體開闢和多餘的陣列拷貝會導致效能的損耗。

所以使用時建議提供合適的容量。

hashtable,Dictionary

hashtable和Dictionary都是雜湊表的實現,很多人說Dictionary內部是由hashtable實現的,這是不恰當的。

hashtable的構造需要裝載因子,裝載因子是0.1 到 1.0 範圍內的數字 ,是內部儲存桶數(count)所佔桶陣列(buckets)桶數(hashsize)的最大比率 ,當桶數大於裝載數(loadsize)時,桶陣列就會擴容

hashtable內部解除雜湊衝突的演算法是雙重雜湊法,是開放地址法中最好的方法之一

而不同的是,Dictionary內部解除雜湊衝突的演算法是鏈地址法,而且Dictionary的構造不需要裝載因子,不受裝載因子的限制 ,如果Dictionary非常小,查詢,插入,刪除等操作擁有近乎O(1)的效率

和ArrayList ,List類似的是Dictionary和hashtable內部也是由陣列實現的,所以構造時也需要提供合適容量,防止效能的損耗。

但我們需要另外注意的是你提供給建構函式的容量不一定會是初始時內建陣列的長度,建構函式內部會選擇一個大於等於你所選擇容量的素數作為真實的初始容量。

HashSet

HashSet是一個無序的能夠保持唯一性的集合。我們也可以把HashSet看作是Dictionary<TKey,TValue>,只不過TKey和TValue都指向同一個物件。內部實現和Dictionary非常相似。 HashSet非常適合在我們需要保持集合內元素唯一性但又不需要按順序排列的時候。

SortedList

SortedList是支援排序的關聯性(鍵值對 )集合 ,內部採用陣列實現,所以和List相同的是,初始化時需要提供一個合適的容量,SortedList內部採用雜湊演算法實現,和Dictionary類似的是,SortedList內部解除雜湊衝突的演算法是鏈地址法。

因為在查詢的時候利用了二分搜尋,所以查詢的效能會好一些,時間複雜度是O(log n)

如果你想要快速查詢,又想集合按照key的順序排列,最後這個集合的操作(新增和移除)比較少的話,就是SortedList了

SortedSet,SortedDictioanry

SortedSet類似於HashSet,但略有不同的是,SortedSet是有序排列,SortedSet內部實現應該是所有集合中最複雜,是依靠紅黑樹的原理實現。

SortedDictioanry和Dictionary的區別與HashSet和SortedSet的區別基本一致,因為SortedDictioanry內部本身就是依靠SortedSet實現的,並且SortDictionary內部順序是以key的順序為排列的

public SortedDictionary(IDictionary<TKey,TValue> dictionary, IComparer<TKey> comparer) {
          if( dictionary == null) {
              ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary);
          }
 
          _set = new TreeSet<KeyValuePair<TKey, TValue>>(new KeyValuePairComparer(comparer));
 
          foreach(KeyValuePair<TKey, TValue> pair in dictionary) {
              _set.Add(pair);
          }            
      }

LinkedList,Stack,Queue

這3個集合我就不多做解釋,完全按這幾個基礎資料結構的原理來實現。不過Stack,Queue內部採用陣列實現,所以也要注意初始化時提供一個恰當的容量啊

相關文章