集合(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!