如何使用 C# 中的 HashSet
譯文鏈接:https://www.infoworld.com/article/3586972/how-to-use-hashset-in-csharp.html
HashSet 是一個(gè)優(yōu)化過(guò)的無(wú)序集合,提供對(duì)元素的高速查找和高性能的set集合操作,而且 HashSet 是在 .NET 3.5 中被引入的,在 System.Collection.Generic 命名空間下,這篇就來(lái)討論一下如何使用這個(gè) HashSet。
要運(yùn)行本篇文章的案例代碼,你需要安裝一下 Visual Studio 2019,如果沒(méi)有的話可以到官網(wǎng)下載一下。
使用 VS 創(chuàng)建一個(gè) .NET Core 控制臺(tái)程序
首先,我通過(guò) VS2019 創(chuàng)建一個(gè) .NET Core 控制臺(tái)程序,創(chuàng)建可以參考下面步驟:
打開(kāi) Visual Studio IDE
點(diǎn)擊創(chuàng)建 Create new project
在 Create new project 窗口上,從模板列表中選擇:Console App (.NET Core)
點(diǎn)擊下一步
在 Configure your new project 界面填好你的項(xiàng)目名稱和存放路徑
這樣我們就創(chuàng)建好了一個(gè)新項(xiàng)目,本文的后面部分就會(huì)在這個(gè)項(xiàng)目里來(lái)給大家分享 HashSet 的一些必備知識(shí)。
HashSet 到底是什么
所謂的HashSet,指的就是 System.Collections.Generic 命名空間下的 HashSet<T> 類,它是一個(gè)高性能,無(wú)序的集合,因此HashSet它并不能做排序操作,也不能包含任何重復(fù)的元素,Hashset 也不能像數(shù)組那樣使用索引,所以在 HashSet 上你無(wú)法使用 for 循環(huán),只能使用 foreach 進(jìn)行迭代,HashSet 通常用在處理元素的唯一性上有著超高的性能。
HashSet<T> 實(shí)現(xiàn)了如下幾個(gè)接口:
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 只能包含唯一的元素,它的內(nèi)部結(jié)構(gòu)也為此做了專門(mén)的優(yōu)化,值得注意的是,HashSet 也可以存放單個(gè)的 null 值,可以得出這么一個(gè)結(jié)論:如何你想擁有一個(gè)具有唯一值的集合,那么 HashSet 就是你最好的選擇,何況它還具有超高的檢索性能。
從 HashSet 中查找一個(gè)元素
如果想判斷某一個(gè)元素是否在 HashSet 內(nèi),建議使用 Contains 進(jìn)行判斷,代碼如下:
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.");elseConsole.WriteLine("The?required?element?isn’t?available.");Console.ReadKey();}HashSet中的元素唯一性
如果你向 HashSet 中插入重復(fù)的元素,它的內(nèi)部會(huì)忽視這次操作而不像別的集合一樣拋出異常,接下來(lái)展示一下代碼:
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();}當(dāng)你執(zhí)行了這個(gè)程序,輸出結(jié)果如下圖:
現(xiàn)在可以考慮一下下面的代碼段,它展示了重復(fù)的元素是如何被剔除的。
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);}}當(dāng)你執(zhí)行完上面的程序,重復(fù)的城市名稱已經(jīng)被移除了。
從 HashSet 中移除元素
從HashSet 中刪除某一個(gè)元素可以調(diào)用 Remove 方法,它的語(yǔ)法結(jié)構(gòu)如下:
public?bool?Remove?(T?item);如果在集合中找到了這個(gè)元素,Remove方法將會(huì)刪除這個(gè)元素并且返回true,否則返回 false。
下面的代碼片段展示了如何使用 Remove 方法刪除 HashSet 中的元素
string?item?=?"D"; if(hashSet.Contains(item)) {hashSet.Remove(item); }如果你想刪除 HashSet 中的所有元素,可以調(diào)用 Clear 方法。
HashSet 的 set操作
HashSet提供了非常多的方法用于 set集合 操作上,比如說(shuō):IntersectWith, UnionWith, IsProperSubsetOf, ExceptWith, 和 SymmetricExceptWith
IsProperSubsetOf
這個(gè) IsProperSubsetOf 用于判斷 HashSet 是否為某一個(gè)集合的完全子集,可以看下面的例子:
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.");如果你執(zhí)行了上面這個(gè)程序,你會(huì)在控制臺(tái)上看到如下的輸出:
UnionWith
UnionWith方法常用于集合的合并,比如說(shuō)下面的代碼:
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); }當(dāng)你執(zhí)行完上面的代碼,SetB 集合會(huì)被 SetA 集合吞掉,最后 SetA 集合將會(huì)是包括:"A", "B", "C", "D", "E", "X", and "Y" 。
IntersectWith
IntersectWith 方法常用于表示兩個(gè) HashSet 的交集,下面的例子或許會(huì)讓你更加理解:
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); }當(dāng)你運(yùn)行了上面的這段程序,只有兩個(gè) HashSet 中都存在的元素才會(huì)輸出到控制臺(tái)中,輸出結(jié)果如下所示:
ExceptWith
ExceptWith 方法表示數(shù)學(xué)上的減法操作,這個(gè)時(shí)間復(fù)雜度是 O(N),假定你有兩個(gè)HashSet 集合,分別叫 setA 和 setB,并且用了下面的語(yǔ)句。
setA.ExceptWith(setB);它返回的元素為:setA中有,setB中沒(méi)有 的最終結(jié)果,如果還不明白的話,使用如下代碼輔助理解:
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); }當(dāng)你執(zhí)行了上面這段程序,元素 B,D,E 將會(huì)輸出到控制臺(tái)上。
SymmetricExceptWith
SymmetricExceptWith 方法常用于修改一個(gè) HashSet 來(lái)存放兩個(gè) HashSet 都是唯一的元素,換句話說(shuō),我要的就是兩個(gè)集合都不全有的元素,如果還不明白的話,考慮下面的代碼段:
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); }當(dāng)你執(zhí)行完上面的代碼,你會(huì)發(fā)現(xiàn),setA中有而setB中沒(méi)有 和 setB中有而setA中沒(méi)有的元素將會(huì)輸出到控制臺(tái)中。
我們知道數(shù)組的平均復(fù)雜度是 O(N),這里的 n 表示數(shù)組里的元素?cái)?shù)量,而訪問(wèn) HashSet 中的某一個(gè)元素,它的復(fù)雜度為 O(1),這個(gè)常量復(fù)雜度就決定了 HashSet 在快速檢索 和執(zhí)行 set集合 操作上是一個(gè)非常好的選擇,你也可以使用 List 去存儲(chǔ)某些有指定順序的元素,同時(shí)也可以包含重復(fù)的值。
總結(jié)
以上是生活随笔為你收集整理的如何使用 C# 中的 HashSet的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: api-hook,更轻量的接口测试工具
- 下一篇: 如何在 C# 中使用 RabbitMQ