首頁>技術>

HashSet 是一個最佳化過的無序集合,提供對元素的高速查詢和高效能的set集合操作,而且 HashSet 是在 .NET 3.5 中被引入的,在 System.Collection.Generic 名稱空間下,這篇就來討論一下如何使用這個 HashSet。

要執行本篇文章的案例程式碼,你需要安裝一下 Visual Studio 2019,如果沒有的話可以到官網下載一下。

使用 VS 建立一個 .NET Core 控制檯程式

首先,我透過 VS2019 建立一個 .NET Core 控制檯程式,建立可以參考下面步驟:

開啟 Visual Studio IDE

Create new project 視窗上,從模板列表中選擇:Console App (.NET Core)

Configure your new project 介面填好你的專案名稱和存放路徑

這樣我們就建立好了一個新專案,本文的後面部分就會在這個專案裡來給大家分享 HashSet 的一些必備知識。

HashSet 到底是什麼

所謂的HashSet,指的就是 System.Collections.Generic 名稱空間下的 HashSet<T> 類,它是一個高效能,無序的集合,因此HashSet它並不能做排序操作,也不能包含任何重複的元素,Hashset 也不能像陣列那樣使用索引,所以在 HashSet 上你無法使用 for 迴圈,只能使用 foreach 進行迭代,HashSet 通常用在處理元素的唯一性上有著超高的效能。

HashSet<T> 實現瞭如下幾個介面:

public class HashSet<T> : System.Collections.Generic.ICollection<T>,System.Collections.Generic.IEnumerable<T>, System.Collections.Generic.IReadOnlyCollection<T>,System.Collections.Generic.ISet<T>,System.Runtime.Serialization.IDeserializationCallback,System.Runtime.Serialization.ISerializable{}

HashSet 只能包含唯一的元素,它的內部結構也為此做了專門的最佳化,值得注意的是,HashSet 也可以存放單個的 null 值,可以得出這麼一個結論:如何你想擁有一個具有唯一值的集合,那麼 HashSet 就是你最好的選擇,何況它還具有超高的檢索效能。

從 HashSet 中查詢一個元素

如果想判斷某一個元素是否在 HashSet 內,建議使用 Contains 進行判斷,程式碼如下:

        static void Main(string[] args)        {            HashSet<string> hashSet = new HashSet<string>();            hashSet.Add("A");            hashSet.Add("B");            hashSet.Add("C");            hashSet.Add("D");            if (hashSet.Contains("D"))                Console.WriteLine("The required element is available.");            else                Console.WriteLine("The required element isn’t available.");            Console.ReadKey();        }
HashSet中的元素唯一性

如果你向 HashSet 中插入重複的元素,它的內部會忽視這次操作而不像別的集合一樣丟擲異常,接下來展示一下程式碼:

        static void Main(string[] args)        {            HashSet<string> hashSet = new HashSet<string>();            hashSet.Add("A");            hashSet.Add("B");            hashSet.Add("C");            hashSet.Add("D");            hashSet.Add("D");            Console.WriteLine("The number of elements is: {0}", hashSet.Count);            Console.ReadKey();        }

當你執行了這個程式,輸出結果如下圖:

現在可以考慮一下下面的程式碼段,它展示了重複的元素是如何被剔除的。

        static void Main(string[] args)        {            string[] cities = new string[] {                "Delhi",                "Kolkata",                "New York",                "London",                "Tokyo",                "Washington",                "Tokyo"            };            HashSet<string> hashSet = new HashSet<string>(cities);            foreach (var city in hashSet)            {                Console.WriteLine(city);            }        }

當你執行完上面的程式,重複的城市名稱已經被移除了。

HashSet 的 set操作

HashSet提供了非常多的方法用於 set集合 操作上,比如說:IntersectWith, UnionWith, IsProperSubsetOf, ExceptWith, 和 SymmetricExceptWith

IsProperSubsetOf

這個 IsProperSubsetOf 用於判斷 HashSet 是否為某一個集合的完全子集,可以看下面的例子:

HashSet<string> setA = new HashSet<string>() { "A", "B", "C", "D" };HashSet<string> setB = new HashSet<string>() { "A", "B", "C", "X" };HashSet<string> setC = new HashSet<string>() { "A", "B", "C", "D", "E" };if (setA.IsProperSubsetOf(setC))   Console.WriteLine("setC contains all elements of setA.");if (!setA.IsProperSubsetOf(setB))   Console.WriteLine("setB does not contains all elements of setA.");

如果你執行了上面這個程式,你會在控制檯上看到如下的輸出:

UnionWith

UnionWith方法常用於集合的合併,比如說下面的程式碼:

HashSet<string> setA = new HashSet<string>() { "A", "B", "C", "D", "E" };HashSet<string> setB = new HashSet<string>() { "A", "B", "C", "X", "Y" };setA.UnionWith(setB);foreach(string str in setA){   Console.WriteLine(str);}

當你執行完上面的程式碼,SetB 集合會被 SetA 集合吞掉,最後 SetA 集合將會是包括:"A", "B", "C", "D", "E", "X", and "Y"

IntersectWith

IntersectWith 方法常用於表示兩個 HashSet 的交集,下面的例子或許會讓你更加理解:

HashSet<string> setA = new HashSet<string>() { "A", "B", "C", "D", "E" };HashSet<string> setB = new HashSet<string>() { "A", "X", "C", "Y"};setA.IntersectWith(setB);foreach (string str in setA){    Console.WriteLine(str);}

當你運行了上面的這段程式,只有兩個 HashSet 中都存在的元素才會輸出到控制檯中,輸出結果如下所示:

ExceptWith

ExceptWith 方法表示數學上的減法操作,這個時間複雜度是 O(N),假定你有兩個HashSet 集合,分別叫 setA 和 setB,並且用了下面的語句。

setA.ExceptWith(setB);

它返回的元素為: setA中有,setB中沒有 的最終結果,如果還不明白的話,使用如下程式碼輔助理解:

HashSet<string> setA = new HashSet<string>() { "A", "B", "C", "D", "E" };HashSet<string> setB = new HashSet<string>() { "A", "X", "C", "Y" };setA.ExceptWith(setB);foreach (string str in setA){   Console.WriteLine(str);}

當你執行了上面這段程式,元素 B,D,E 將會輸出到控制檯上。

SymmetricExceptWith

SymmetricExceptWith 方法常用於修改一個 HashSet 來存放兩個 HashSet 都是唯一的元素,換句話說,我要的就是兩個集合都不全有的元素,如果還不明白的話,考慮下面的程式碼段:

HashSet<string> setA = new HashSet<string>() { "A", "B", "C", "D", "E" };HashSet<string> setB = new HashSet<string>() { "A", "X", "C", "Y" };setA.SymmetricExceptWith(setB);foreach (string str in setA){  Console.WriteLine(str);}

當你執行完上面的程式碼,你會發現,setA中有而setB中沒有 和 setB中有而setA中沒有的元素將會輸出到控制檯中。

我們知道陣列的平均複雜度是 O(N),這裡的 n 表示數組裡的元素數量,而訪問 HashSet 中的某一個元素,它的複雜度為 O(1),這個常量複雜度就決定了 HashSet 在快速檢索 和執行 set集合 操作上是一個非常好的選擇,你也可以使用 List 去儲存某些有指定順序的元素,同時也可以包含重複的值。

16
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 用 C# 實現一個簡單的日誌框架