1. 為什麼選擇使用泛型集合 存在的問題 ArrayList arrylist = new ArrayList() { 14, "hello", 29.7, true}; arrylist.Add("world");// object double dsum = 0; foreach(var i ...
存在的問題
ArrayList arrylist = new ArrayList() { 14, "hello", 29.7, true}; arrylist.Add("world");// object double dsum = 0; foreach(var item in arrylist) { dsum += Convert.ToDouble(item); // 出現異常 }
1、存取數據需要進行裝箱拆箱 2、數據類型轉換存在隱患
性能對比
非泛型集合性能
[Test] public void Test1() { Stopwatch watch = new Stopwatch(); watch.Start(); ArrayList arrayList = new(); for (int i = 0; i < 2000000; i++) { arrayList.Add(i); // 裝箱 } long sum = 0; foreach (var item in arrayList) { sum += Convert.ToInt64(item); } watch.Stop(); Console.WriteLine("非泛型集合耗時(ms):"+watch.ElapsedMilliseconds); }
輸出結果:非泛型集合耗時(ms):258
泛型集合性能
[Test] public void Test1() { Stopwatch watch = new Stopwatch(); watch.Start(); var arrayList = new List<int>(); for (int i = 0; i < 2000000; i++) { arrayList.Add(i); } long sum = 0; foreach (var item in arrayList) { sum += Convert.ToInt64(item); } watch.Stop(); Console.WriteLine("泛型集合耗時(ms):"+watch.ElapsedMilliseconds); }
輸出結果:泛型集合耗時(ms):25
2. List<T> 集合
使用場景:
-
在Linq 中比較常見
-
存儲數據
聲明
聲明泛型集合
List<T> 集合名=new List<T>()
例如:
//值類型 List<int> list = new List<int>(); //引用類型 List<PersonModel> personList = new List<PersonModel>()
1、T只是占位符,會被傳遞的數據類型替換。 2、實例化List時傳入相對應的數據類型 3、長度以2倍速度擴容
List<T> 常用屬性
Count | List集合中當前存儲的元素個數 |
---|---|
Capacity | List集合當前容量 Capacity>=Count |
List<int> list = new List<int>() { 2, 3, 7, 5, 9 }; // 集合初始化器 Count : 5 Capacity : 8
List<T> 常用方法
Add() | 添加到List集合尾部 Add(元素) 如:strlist.Add(“me”) |
---|---|
Insert() | 添加到List集合指定位置 Insert(下標,元素) 如:strlist.Insert(2,”Hi”) |
Remove() | 刪除List集合中的元素 Remove(元素) 如:strlist.Remove(“c”) |
RemoveAt() | 刪除List集合中指定下標的元素 RemoveAt(下標)如:strlist.RemoveAt(3) |
RemoveRange() | 刪除List集合中指定範圍的元素 RemoveRange(下標,個數), 如:strlist.RemoveRange(1,2) |
Clear() | 清空List集合中所有元素 Clear() |
First() | 返回List集合中第一個元素 |
FirstOrDefault () | 返回List集合中第一個元素為空是返回預設值 |
Last() | 返回List集合中最後一個元素 |
LastOrDefault () | 返回List集合最後一個元素為空時返回預設值 |
List<int> list = new List<int>() { 2, 3, 7, 5, 9 }; list.Add(10); // 2, 3, 7, 5, 9,10 list.Insert(2,6); // 2, 3,6, 7, 5, 9,10 list.Remove(2); // 3,6, 7, 5, 9,10 list.RemoveAt(0); // 6, 7, 5, 9,10 list.RemoveRange(1,2); // 6,9,10 list.First();// 6 list.FirstOrDefault(); // 6 list.Last();// 10 list.LastOrDefault(); // 10 list.Clear(); // 集合為空
3. Stack<T> 棧
特點:先進後出,後進先出
[Test] public void Test1() { Stack<int> stack = new Stack<int>(); stack.Push(10); // 壓棧 10 stack.Push(9); // 9,10 stack.Push(8); // 8,9,10 var peek = stack.Peek(); // 8 返回最頂的元素 var item = stack.Pop();// 8 , 移除並返回最頂的元素,stack 還剩下 9,10 foreach (var s in stack) { Console.WriteLine(s); // 輸出 9 ,10 } }
4. Queue<T> 隊列
特點:先進先出
[Test] public void Test1() { Queue<int> queue = new Queue<int>(); queue.Enqueue(10); // 入隊 queue.Enqueue(9); queue.Enqueue(8); queue.Enqueue(7); Console.WriteLine(queue.Peek()); // 返回最開始的元素,10(出隊方向的第一個元素) var item = queue.Dequeue();// 刪除出隊方向的第一個元素 並返回它的值 ,10 foreach (var q in queue) { Console.WriteLine(q); // 9,8,7 } }
5. SortedList<TKey,TValue> 類
-
命名空間:
-
程式集: System.Collections.dll
表示基於相關的
-
TKey 集合中的鍵的類型。
-
TValue 集合中值的類型。
快速入門
[Test] public void Test1() { // 成績列表 SortedList<string,int> scoreList = new SortedList<string,int>(); scoreList["b"] = 80; scoreList["c"] = 50; scoreList.Add("a",100); foreach (var score in scoreList) { Console.WriteLine($"科目:{score.Key},成績:{score.Value}"); } }
輸出結果:
科目:a,成績:100
科目:b,成績:80
科目:c,成績:50
詳細案例
using System; using System.Collections.Generic; public class Example { public static void Main() { // 創建一個鍵值對都是string 類型的集合 SortedList<string, string> openWith = new SortedList<string, string>(); // 初始化一些沒有重覆鍵的元素,但對應的值,有些元素是重覆的 openWith.Add("txt", "notepad.exe"); openWith.Add("bmp", "paint.exe"); openWith.Add("dib", "paint.exe"); openWith.Add("rtf", "wordpad.exe"); // 如果添加一個已經存在的鍵值對,則會拋出異常 try { openWith.Add("txt", "winword.exe"); } catch (ArgumentException) { Console.WriteLine("An element with Key = \"txt\" already exists."); } // 元素的鍵可作為集合的索引來訪問元素 Console.WriteLine("For key = \"rtf\", value = {0}.", openWith["rtf"]); // 通過鍵索引,可修改其所關聯的值 openWith["rtf"] = "winword.exe"; Console.WriteLine("For key = \"rtf\", value = {0}.", openWith["rtf"]); // 如果鍵不存在,則會新增一個鍵值對數據 openWith["doc"] = "winword.exe"; // 如果請求的鍵不存在,則會拋出異常 try { Console.WriteLine("For key = \"tif\", value = {0}.", openWith["tif"]); } catch (KeyNotFoundException) { Console.WriteLine("Key = \"tif\" is not found."); } // 當一個程式經常要嘗試的鍵,結果卻不是 在列表中,TryGetValue可以是一個更有效的 // 獲取值的方法。 string value = ""; if (openWith.TryGetValue("tif", out value)) { Console.WriteLine("For key = \"tif\", value = {0}.", value); } else { Console.WriteLine("Key = \"tif\" is not found."); } // 判斷是否包含鍵 if (!openWith.ContainsKey("ht")) { openWith.Add("ht", "hypertrm.exe"); Console.WriteLine("Value added for key = \"ht\": {0}", openWith["ht"]); } // 遍歷迴圈,元素被檢索為KeyValuePair對象 Console.WriteLine(); foreach( KeyValuePair<string, string> kvp in openWith ) { Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value); } // 獲取集合中的Values 列表 IList<string> ilistValues = openWith.Values; // 列印出所有的值列表 Console.WriteLine(); foreach( string s in ilistValues ) { Console.WriteLine("Value = {0}", s); } // 通過索引獲取值 Console.WriteLine("\nIndexed retrieval using the Values " + "property: Values[2] = {0}", openWith.Values[2]); // 獲取所有的Key IList<string> ilistKeys = openWith.Keys; // 列印出所有的鍵列表 Console.WriteLine(); foreach( string s in ilistKeys ) { Console.WriteLine("Key = {0}", s); } // 通過索引獲取Key Console.WriteLine("\nIndexed retrieval using the Keys " + "property: Keys[2] = {0}", openWith.Keys[2]); // 移除元素 Console.WriteLine("\nRemove(\"doc\")"); openWith.Remove("doc"); if (!openWith.ContainsKey("doc")) { Console.WriteLine("Key \"doc\" is not found."); } } } /* This code example produces the following output: An element with Key = "txt" already exists. For key = "rtf", value = wordpad.exe. For key = "rtf", value = winword.exe. Key = "tif" is not found. Key = "tif" is not found. Value added for key = "ht": hypertrm.exe Key = bmp, Value = paint.exe Key = dib, Value = paint.exe Key = doc, Value = winword.exe Key = ht, Value = hypertrm.exe Key = rtf, Value = winword.exe Key = txt, Value = notepad.exe Value = paint.exe Value = paint.exe Value = winword.exe Value = hypertrm.exe Value = winword.exe Value = notepad.exe Indexed retrieval using the Values property: Values[2] = winword.exe Key = bmp Key = dib Key = doc Key = ht Key = rtf Key = txt Indexed retrieval using the Keys property: Keys[2] = doc Remove("doc") Key "doc" is not found. */
6. Dictionary<TKey,TValue> 字典集合
HashTable
HashTable 哈唏表, 也叫散列表,有關詳細的Hash解說,請查看文章:
值得強調的是:常見的Hash演算法有MD5(彩虹表,Hash撞庫), SHA1 均已被破解,目前推薦的Hash 演算法是:SHA2-256。
彩虹表: 用來存放所有hash值的部分hash值字典。然後通過碰撞破解密碼
using System; using System.Collections; class Example { public static void Main() { Hashtable openWith = new Hashtable(); // 初始化一批數據,不可出現重覆鍵 openWith.Add("txt", "notepad.exe"); openWith.Add("bmp", "paint.exe"); openWith.Add("dib", "paint.exe"); openWith.Add("rtf", "wordpad.exe"); // 如果出現重覆鍵,則會拋出異常 try { openWith.Add("txt", "winword.exe"); } catch { Console.WriteLine("An element with Key = \"txt\" already exists."); } // 通過索引訪問 Console.WriteLine("For key = \"rtf\", value = {0}.", openWith["rtf"]); // 修改索引所關聯的值 openWith["rtf"] = "winword.exe"; Console.WriteLine("For key = \"rtf\", value = {0}.", openWith["rtf"]); // 給一個不存在的鍵賦值,則會新增 openWith["doc"] = "winword.exe"; // 判斷是否包含 if (!openWith.ContainsKey("ht")) { openWith.Add("ht", "hypertrm.exe"); Console.WriteLine("Value added for key = \"ht\": {0}", openWith["ht"]); } // 遍歷迴圈,元素被檢索為 DictionaryEntry 對象 Console.WriteLine(); foreach( DictionaryEntry de in openWith ) { Console.WriteLine("Key = {0}, Value = {1}", de.Key, de.Value); } // 獲取所有的值集合 ICollection valueColl = openWith.Values; // 遍歷值集合 Console.WriteLine(); foreach( string s in valueColl ) { Console.WriteLine("Value = {0}", s); } // 獲取所有的鍵 ICollection keyColl = openWith.Keys; // 遍歷鍵集合 Console.WriteLine(); foreach( string s in keyColl ) { Console.WriteLine("Key = {0}", s); } // 移除鍵值對 Console.WriteLine("\nRemove(\"doc\")"); openWith.Remove("doc"); if (!openWith.ContainsKey("doc")) { Console.WriteLine("Key \"doc\" is not found."); } } }
不建議將類用於
Hashtable
新開發。 相反,我們建議使用泛型
Dictionary<TKey,TValue>
表示鍵和值的集合。
-
TKey : 字典中的鍵的類型。
-
TValue : 字典中的值的類型。
Dictionary<string, string> openWith = new Dictionary<string, string>(); // 初始化數據,不能存在重覆鍵 openWith.Add("txt", "notepad.exe"); openWith.Add("bmp", "paint.exe"); openWith.Add("dib", "paint.exe"); openWith.Add("rtf", "wordpad.exe"); // 添加重覆鍵會拋出異常 try { openWith.Add("txt", "winword.exe"); } catch (ArgumentException) { Console.WriteLine("An element with Key = \"txt\" already exists."); } // 通過索引取值 Console.WriteLine("For key = \"rtf\", value = {0}.", openWith["rtf"]); // 給已存在的鍵值索引賦值 openWith["rtf"] = "winword.exe"; Console.WriteLine("For key = \"rtf\", value = {0}.", openWith["rtf"]); // 如果不存在,則會新增 openWith["doc"] = "winword.exe"; // 如果訪問一個不存在的索引值,則會拋出異常 try { Console.WriteLine("For key = \"tif\", value = {0}.", openWith["tif"]); } catch (KeyNotFoundException) { Console.WriteLine("Key = \"tif\" is not found."); } // tryValue 嘗試取值 string value = ""; if (openWith.TryGetValue("tif", out value)) { Console.WriteLine("For key = \"tif\", value = {0}.", value); } else { Console.WriteLine("Key = \"tif\" is not found."); } // 判斷是否包含鍵 if (!openWith.ContainsKey("ht")) { openWith.Add("ht", "hypertrm.exe"); Console.WriteLine("Value added for key = \"ht\": {0}", openWith["ht"]); } // 遍歷迴圈,元素被檢索為 KeyValuePair 對象 Console.WriteLine(); foreach( KeyValuePair<string, string> kvp in openWith ) { Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value); } // 獲取所有的值集合 Dictionary<string, string>.ValueCollection valueColl = openWith.Values; // 遍歷值集合 Console.WriteLine(); foreach( string s in valueColl ) { Console.WriteLine("Value = {0}", s); } // 獲取所有的鍵集合 Dictionary<string, string>.KeyCollection keyColl = openWith.Keys; // 遍歷鍵集合 Console.WriteLine(); foreach( string s in keyColl ) { Console.WriteLine("Key = {0}", s); } // 移除鍵值對 Console.WriteLine("\nRemove(\"doc\")"); openWith.Remove("doc"); if (!openWith.ContainsKey("doc")) { Console.WriteLine("Key \"doc\" is not found."); }
備註
檢索速度取決於為
TKey
類型指定的哈希演算法的質量。
只要對象用作鍵,