C#集體型別( Collections in C#)
# 集合是.NET FCL(Framework Class Library)中很重要的一部分,也是我們開發當中最常使用到的功能之一,幾乎是無所不在。俗話說知其然,知其所以然,平常看到IEnumerable,IEnumerator,ICollection是不是知道他們之間各自的差別?除了List和Dictionary以外,你還用過哪些它的集合類別?廢話少說,今天我們就來看一些這些定義集合類別的介面以及他們的實作。
先來看一下,FCL為我們提供了哪些介面:
#
public interface IEnumerator { bool MoveNext(); object Current { get; } void Reset(); }
IEnumerator定義了我們遍歷集合的基本方法,以便我們可以實現單向向前的訪問集合中的每一個元素。而IEnumerable只有一個方法GetEnumerator即得到遍歷器。
public interface IEnumerable { IEnumerator GetEnumerator(); }
注意:我們常用的foreach即是一種語法糖,實際上還是呼叫Enumerator裡面的Current和MoveNext實現的遍歷功能。
List<string> list = new List<string>() { "Jesse", "Chloe", "Lei", "Jim", "XiaoJun" }; // Iterate the list by using foreach foreach (var buddy in list) { Console.WriteLine(buddy); } // Iterate the list by using enumerator List<string>.Enumerator enumerator = list.GetEnumerator(); while (enumerator.MoveNext()) { Console.WriteLine(enumerator.Current); }
上面的程式碼中所使用的foreach和enumerator到IL中最後都會被翻譯成enumerator的MoveNext和Current。
#
# IEnumerable是一個很有用的接口,實作它的好處包括:
支援foreach語句
# 作為一個標準的集合類別與其它類別庫進行互動
# 滿足更複雜的集合介面的需求
# 支援集合初始化器
當然實作的方法也有很多,如下:
如果我們集合是透過封裝其它集合類別而來的,那麼我們可以直接傳回這個集合的enumerator
透過yield return 來回傳
實作我們自己的IEnumerator來實作
# 這裡為大家示範如何透過yield來實現返回enumerator
public class BuddyList : IEnumerable { private string[] data= new string[] { "Jesse", "Chloe", "Lei", "Jim", "XiaoJun" }; public IEnumerator GetEnumerator() { foreach (var str in data) { yield return str; } } } var myBuddies= new BuddyList(); foreach (var str in myBuddies) { Console.WriteLine(str); }
從最上面第一張圖我們可以知道,ICollection是直接繼承自IEnumerable。而實際上也是如此,我們可以說ICollection比IEnumerable多支援一些功能,不只提供基本的遍歷功能,還包括:
統計集合與元素數量
# 取得元素的下標
# 判斷是否存在
# 將元素新增至未尾
# 移除元素等等。 。 。
ICollection 與ICollection
# IList則是直接繼承自ICollection和IEnumerable。所以它包括兩者的功能,並且支援根據下標存取和添加元素。 IndexOf, Insert, RemoveAt等等。我們可以這樣說,IEnumerable支援的功能最少,只有遍歷。而ICollection支援的功能稍微多一點,不但有遍歷還有維護這個集合的功能。而IList是最全的版本。
#
這個是在Framework4.5中新增的介面類型,可以被看作是IList
IDictionary提供了對鍵值對集合的訪問,也是繼承了ICollection
# 關聯性集合類別即我們常說的鍵值對集合,允許我們透過Key來存取和維護集合。我們先來看看 FCL為我們提供了哪些泛型的關聯性集合類別:
#
Dictionary
#
SortedDictionary
SortedList
Dictionary
Dictionary
作為TKey的類型必須實作GetHashCode()和Equals() 或提供一個IEqualityComparer#否則操作可能會出現問題。
#
SortedDictionary
#
SortedList
# 非關聯性集合就是不用key運算的一些集合類,通常我們可以用元素本身或下標來運算。 FCL主要為我們提供了以下幾種非關聯性的泛型集合類別。
List
#
LinkedList
#
HashSet
#
SortedSet
#
Stack
#
Queue
泛型的List 類別提供了不限制長度的集合類型,List在內部維護了一定長度的陣列(預設初始長度是4),當我們插入元素的長度超過4或初始長度的時候,會去重新建立一個新的數組,這個新數組的長度是初始長度的2倍(不永遠是2倍,當發現不斷的要擴充的時候,倍數會變大),然後把原來的數組拷貝過來。所以如果知道我們將要用這個集合裝多少個元素的話,可以在創建的時候指定初始值,這樣就避免了重複的創建新數組和拷貝值。
另外的話由於內部實質是一個數組,所以在List的未必添加數據是比較快的,但是如果在數據的頭或者中間添加刪除數據相對來說更低效一些因為會影響其它數據的重新排列。
# LinkedList在內部維護了一個雙向的鍊錶,也就是說我們在LinkedList的任何位置添加或刪除資料其效能都是很快的。因為它不會導致其它元素的移動。一般情況下List已經夠我們使用了,但是如果對這個集合在中間的添加刪除操作非常頻繁的話,就建議使用LinkedList。
#
HashSet是一個無序的能夠保持唯一性的集合。我們也可以把HashSet看成是Dictionary
HashSet不支援下標存取。
# SortedSet和HashSet,就像SortedDictionary和Dictionary一樣,還記得這兩個的差別麼? SortedSet內部也是二元樹,用來支援依序的排列元素。
後進先出的隊列
不支援按下標訪問
#
先進先出的隊列
不支援按下標訪問
#
集合 |
順序排列 |
連順存儲 |
直接存取方式 |
訪問時間 |
操作時間 |
備註 |
#
Dictionary |
|
是 |
Key |
Key: O(1)
|
O(1) |
存取效能最快,不支援排序 |
#
SortedDinctionary |
順序排列 |
否 |
Key |
Key: |
O(log n) |
快速存取和支援排序的折衷 |
#
SortedList |
順序排列 |
是 |
Key |
Key: O(log n)
|
O(n) |
和SortedDictionary相似,只是內部以資料取代樹作為儲存結構。 |
#
List |
使用者可以精確控制元素的位置 |
是 |
Index |
Index: O(1) Value: O(n)
|
O(n) |
最適合需要直接存取每一個元素的少量集合。 |
#
LinkedList |
使用者可以精確控制元素的位置 |
否 |
不支援 |
Value: O(n)
|
O(1) |
最適合不需要直接存取單一元素,但是在集合中添加/移除非常頻繁的場景。 |
#
HashSet |
不支援 |
是 |
Key |
Key: O(1)
|
O(1) |
能保持元素唯一性的集合。不支援排序 |
#
SortedSet |
順序排列 |
否 |
Key |
Key: O(log n)
|
O(log n) |
能保持元素唯一性並且支援排序。 |
#
Stack |
LIFO |
是 |
只能取得頂部元素 |
Top: O(1) |
O(1) |
|
#
Queue |
FIFO |
是 |
只能獲底部元素 |
Front: O(1) |
O(1) |
|
# 泛型集合類別是在.NET2.0的時候出來的,也就是說在1.0的時候是沒有這麼方便的東西的。現在基本上我們已經不使用這些集合類別了,除非在做一些和舊程式碼保持相容的工作的時候。來看看1.0時代的.NET程式設計師們都有哪些集合類別可以用。
ArraryList
#
後來被List
HashTable 後來被Dictionary
#
Queue 後來被Queue
#
SortedList 後來被SortedList
#
Stack 後來被Stack
ConcurrentQueue 線程安全版本的Queue
# ConcurrentStack執行緒安全版本的Stack
# ConcurrentBag執行緒安全的物件集合
# ConcurrentDictionary線程安全的Dictionary
# BlockingCollection
# .NET為我們提供的集合類別是我們很常用的工具類別之一,希望這篇文章能幫助大家更好的認識這些集合類別。當然,個人感覺還有不完美的地方,比如說HashTable和Binary Search Tree就沒有細究下去,包括單向鍊錶和雙向鍊錶之間的比較本文也沒有提及。有興趣的朋友可以深入了解一下。
以上是詳解C#集合類型大盤點的圖文程式碼的詳細內容。更多資訊請關注PHP中文網其他相關文章!