C#各類集合介紹

江北、發表於2020-07-12

集合(Collection)類是專門用於資料儲存和檢索的類。這些類提供了對棧(stack)、佇列(queue)、列表(list)和雜湊表(hash table)的支援。大多數集合類實現了相同的介面。

平常在工作中List<T>集合是用的最多的,其次是Array(陣列).今天整理一下各類形式的集合,不用就容易忘,必須要記錄一下.

Array

Array:在記憶體上是連續分配的(可定義長度,也可不定義長度),Array中的元素型別要一樣。

Array通過座標(索引)訪問,讀取、修改快---增刪慢

如果Array定義了長度,資料項就不能超過Array中的長度範圍.

ArrayList

ArrayList:不定長度的,連續分配的

//元素沒有型別限制 任何元素都當成object處理,如果是值型別會有裝箱操作
ArrayList arrayList = new ArrayList();
arrayList.Add("object");//可以放string
arrayList.Add(Enumerable.Range(1,100).ToArray());//可以放Array
Func<string, int> func = m => 1;
arrayList.Add(func);//可以放Delegate
//移除資料
arrayList.RemoveAt(0);//通過索引座標移除
arrayList.Remove("object");//匹配第一個元素值,滿足就移除

List

List:也是Array,記憶體上都是連續擺放的;不定長;泛型,保證型別安全,避免裝箱拆箱(都是統一的型別)

var list = new List<int>() { 1, 2, 3 };
list.Add(1);
list.AddRange(new List<int> { 4, 5, 6 });//批量新增
list.Any();//判斷是否有資料
list.Clear();//清除所有資料
list.ForEach((m) => { });//foreach迴圈,引數=>viod委託
list.Skip(1).Take(2);//取索引為0之後的兩條資料
//... ...

以上三種都屬於Array型別,只要是Array型別都是讀取快(可通過索引訪問),增刪慢.

LinkedList

LinkedList:雙向連結串列 元素不連續分配,每個元素都有記錄前後節點。

//在頭部和尾部都標識了上一個元素和下一個元素所處位置
LinkedList<int> list = new LinkedList<int>();
list.AddLast(1);
list.AddFirst(1);
bool isBool = list.Contains(1);//判斷連結串列中是否有1這個元素

LinkedListNode<int> list1 = list.Find(123);//找到元素123的這個節點
list.AddBefore(list1, 0);//前面增加
list.AddAfter(list1, 0);//後面增加

list.Remove(1);
list.Remove(list1);//根據節點刪除
list.RemoveFirst();
list.RemoveLast();
list.Clear();

 連結串列不能通過元素索引訪問。找元素只能遍歷。增刪比較快,增加或刪除,只需把這個元素的前後兩個元素指向的元素節點改一下。

Queue

Queue 佇列,就是連結串列  先進先出

//用處;放任務延遲執行  A不斷寫入任務,B不斷獲取任務執行  每次拿最近的一個任務
Queue<string> queue = new Queue<string>();
queue.Enqueue("object");//新增資料
queue.Enqueue("object1");
foreach (var item in queue)
{
    Console.WriteLine(item);
}
queue.Dequeue();//獲取最先進入佇列的元素,獲得並移除
queue.Peek();//獲取但不移除

Stack

Stack:棧 也是連結串列, 先進後出 先產生的資料最後使用

Stack<string> stack = new Stack<string>();
stack.Push("object");//新增資料
stack.Push("object1");
stack.Pop();//獲取最後進入佇列的元素  獲得並移除
stack.Peek();//獲取不移除

C#中(執行緒)棧的記憶體釋放也是一樣,先例項化的物件最後釋放(在棧中宣告的變數,最先宣告的最後GC)

 陣列和連結串列(LinkedList、Queue、Stack)是他們記憶體分配的本質而區分的,元素連續分配和不連續分配.

Set型別集合

HashSet

HashSet:hash分佈,元素間沒關係(不用記錄前後節點),動態增加.

HashSet<string> hashSet = new HashSet<string>();
hashSet.Add("object1");//新增元素
hashSet.Add("object2");
hashSet.Add("object3");
hashSet.Add("object1");//會自動去重
int count = hashSet.Count;//獲得數量
hashSet.Contains("object");

HashSet<string> hashSet1 = new HashSet<string>();
hashSet1.Add("object1");
hashSet1.Add("object2");
hashSet1.Add("object4");
hashSet1.SymmetricExceptWith(hashSet);//補集:不包含hashSet1和hashSet共有的所有元素
hashSet1.UnionWith(hashSet);//並集:hashSet1和hashSet所有的元素
hashSet1.ExceptWith(hashSet);//差集:hashSet1有的元素而hashSet沒有的元素
hashSet1.IntersectWith(hashSet);//交集:共同的元素
hashSet1.ToList();
hashSet1.Clear();

SortedSet

SortedSet:排序集合  去重+排序.SortedSet也可以做交差並補.

//IComparer<T>? comparer  自定義物件要排序,就用這個指定
SortedSet<string> sortedSet = new SortedSet<string>();
sortedSet.Add("object1");
sortedSet.Add("object2");
sortedSet.Add("object1");//會自動去重
int count = sortedSet.Count;
sortedSet.Contains("object1");

HashTable(key-value)型別集合

Hashtable:拿著key計算一個記憶體地址,然後放入key-value。長度不定,可以動態增加。放入的都是object型別,所以避免不了裝箱拆箱。

 //如果不同的key得到相同的記憶體地址,第二個在前面的地址上+1,由此會形成陣列
 //查詢的時候,如果地址對應的key不對,那就+1查詢//查詢個資料  一次定位,增刪查改都很快
 //資料太多 重複定位,效率就下去了
 Hashtable hashtable = new Hashtable();
 hashtable.Add("key", "value");
 hashtable[111] = 222;//KEY,VALUE
 foreach (DictionaryEntry item in hashtable)
 {
     Console.WriteLine(item.Key.ToString());
     Console.WriteLine(item.Value.ToString());
 }
 //執行緒安全
 Hashtable.Synchronized(hashtable);//只有一個執行緒寫,多個執行緒讀

Dictionary:相當於泛型版本的HashTable.因為資料基於泛型,減少了裝箱拆箱的消耗.

Dictionary<int, string> pairs = new Dictionary<int, string>();
pairs.Add(1, "object1");
pairs[2] = "object2";
foreach (var item in pairs)
{
    Console.WriteLine(item.Key.ToString(), item.Value);
}
pairs.ContainsKey(1);//是否存在這個key
//... ...

SortedDictionary:排序字典,依據key進行排序.因為要排序,所以增刪改慢,多了一個排序

SortedDictionary<int, string> pairs = new SortedDictionary<int, string>();
//根據key依次排序
pairs.Add(1, "object1");
pairs.Add(2, "object2");
pairs.Add(3, "object3");
pairs.Add(4, "object4");

SortedList: 也是key,value形式,自動排序.不能重複新增,key重複會報錯

IComparer comparer 自定義物件要排序,就用這個指定

SortedList sortedList = new SortedList();
sortedList.Add("2", "1");
var keyList = sortedList.GetKeyList();
var valueList = sortedList.GetValueList();
sortedList.TrimToSize();//用於最小化集合的記憶體開銷
sortedList.Remove("1");//根據key值移除
sortedList.RemoveAt(0);//根據索引移除
sortedList.Clear();//移除所有元素
字典集合執行緒不安全(非執行緒安全),這塊記憶體多個執行緒都可以改
ConcurrentQueue 執行緒安全版本的Queue
ConcurrentStack 執行緒安全版本的Stack
ConcurrentBag (List集合是非執行緒安全的)ConcurrentBag執行緒安全版本的物件集合
ConcurrentDictionary 執行緒安全版本的Dictionary
BlockingCollection 執行緒安全集合

ArrayList和List都實現了IList介面,可以通過索引訪問元素,像連結串列這種就不可以通過索引訪問元素.

但是連結串列這種集合繼承了ICollection型別的介面,因此可獲得集合的長度(長度不定的集合都繼承了ICollection介面)

IEnumerable\ICollection\IList\IQueryable
介面是標識功能的.不同的介面拆開就是為了介面隔離.實現不同的介面表明這個集合的功能不同.

任何資料集合都實現IEnumerable,IEnumerable為不同的資料結構(各種集合)提供了統一的資料訪問方式(foreach)=》迭代器模式

 the end!

相關文章