第五單元 泛型集合

来源:https://www.cnblogs.com/xuyubing/archive/2023/11/22/17850532.html
-Advertisement-
Play Games

1. 為什麼選擇使用泛型集合 存在的問題 ArrayList arrylist = new ArrayList() { 14, "hello", 29.7, true}; arrylist.Add("world");// object ​ double dsum = 0; foreach(var i ...


1. 為什麼選擇使用泛型集合

存在的問題

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

使用場景:

  1. 在Linq 中比較常見

  2. 存儲數據

聲明

聲明泛型集合
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> 常用屬性

CountList集合中當前存儲的元素個數
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> 類

表示基於相關的 IComparer 實現按鍵進行排序的鍵/值對的集合。

  • 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(散列函數)_百度百科 (baidu.com)

值得強調的是:常見的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 類。 有關詳細信息,請參閱不應在GitHub上使用非泛型集合

 

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.");
}

 

Dictionary泛型類提供從一組鍵到一組值的映射。 每次對字典的添加都包含一個值和與其關聯的鍵。 通過使用其鍵檢索值的速度非常快,接近 O (1) ,因為類 Dictionary 作為哈希表實現。

備註

檢索速度取決於為 TKey類型指定的哈希演算法的質量。

只要對象用作鍵, Dictionary它就不能以任何方式更改影響其哈希值。 每個鍵 Dictionary 都必鬚根據字典的相等比較器是唯一的。 如果鍵的類型是引用類型TValue,則鍵不能null,但值可以是。

Dictionary 需要相等實現來確定鍵是否相等。 可以使用接受comparer參數的構造函數指定泛型介面的

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在數據科學計算、機器學習、以及深度學習領域,Python 是最受歡迎的語言。Python 在數據科學領域,有非常豐富的包可以選擇,numpy、scipy、pandas、scikit-learn、matplotlib。 但這些庫都僅僅受限於單機運算,當數據量很大時,比如50GB甚至500GB的數據集, ...
  • 創建資料庫 (xxl-job) 導入相關表 Sql SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- -- Table structure for xxl_job_group -- DROP TABLE IF EXISTS `xxl_job_grou ...
  • 原文鏈接:https://openaigptguide.com/grok-ai/ Grok AI是由馬斯克推出的一款高級別的人工智慧大語言模型,旨在幫助軟體開發者以不同的口頭語言交流和表達。它是基於多種深度學習大規模固定模型架構,如ELMo、BERT和GPT,以及更多新的模式,使軟體開發者能夠快速設 ...
  • 公眾號「架構成長指南」,專註於生產實踐、雲原生、分散式系統、大數據技術分享。 在本教程中,您將通過大量示例來學習 Java 8 Stream API。 Java 在 Java 8 中提供了一個新的附加包,稱為 java.util.stream。該包由類、介面和枚舉組成,允許對元素進行函數式操作。 您 ...
  • 主要介紹了Java的Spring框架中的註解編程。第一章首先介紹了註解編程的概念,即在類或方法上添加特定的註解來完成特定功能的開發。然後解釋了為什麼要學習註解編程,主要原因是註解開發方便且與Spring框架的發展潮流相符合。接著介紹了註解的作用,包括替換XML配置和替換介面實現調用雙方的契約性。第四... ...
  • 一個提供互動式的Web UI用於生成相容MyBatisPlus框架的相關功能代碼的工具,代碼生成包括Entity、Mapper、Mapper.xml、Service、Controller等。 ...
  • 註:之前搭建的windows失敗,因為最終發現openface開源代碼中的torch_neural_net.py的某一路徑並不是windows的文件路徑,所以直接改用最簡便的docker使用。 實現需求目標: 實現兩張照片對人臉進行比對判斷是否為同一個人 openface環境搭建步驟 安裝docke ...
  • 前幾天寫了一篇文章【淺談WPF之控制項模板和數據模板】,有粉絲反饋說這兩種模板容易弄混,不知道什麼時候該用控制項模塊,什麼時候該用數據模板,以及template和itemtemplate之間的關係等,今天專門寫一篇文章,簡述WPF中各種模板及其相互關係。僅供學習分享使用,如有不足之處,還請指正。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...