在C#中引入HashSet
在.NET框架中,有幾個類可用於執行這些操作。一些課程如下:
- 列表
- 字典
- 哈希集
- 隊列
集合
在C#編程中,像ArrayList,List這樣的集合,只需添加其中的值,而不檢查任何重復。為了避免這種重復的數據存儲,.NET提供集合名稱集。這是一個具有不同項目的集合類型。
有兩種類型的集合,SortedSet和HastSet。SortedSet按照排序順序存儲數據,也可以消除重復。
哈希集 vs SortedSet
這兩個類都存儲非重復的項目。但是,如果要執行性能,並且不關心項目是否未分類存儲,則進入HashSet。但是,如果您希望項目在插入后進行排序,但可以進行性能打擊,請選擇“排序”。
本文分為六個部分,分別如下:
第1節:HastSet的特點
第2節:消除HashSet中的重復數據條目
第3節:使用UnionWith()方法修改HashSet方法
第4節:使用ExceptWith()方法
修改Hashset第5節:使用SymmetricExceptWith()方法修改Hashset
第6節:檢查添加,刪除等操作的性能,包含HashSet和List。
讓我們開始吧
第1節:HastSet的特點
這是HashSet的一些突出特點。
- 這個類代表一組值。
- 這個類提供了高性能的操作。
- 這是一組不包含重復元素的集合,並且其中存儲的元素沒有特定的順序。
- 在.NET Framework 4.6版本中,HashSet 實現IReadOnlyCollection 界面連同ISet 接口。
- 哈希集類對其中存儲的元素數量沒有任何最大容量。隨着元素數量的增加,這種容量不斷增加。
第2節:消除C#HashSet中的重復
步驟1:打開Visual Studio並創建名稱為CS_Using_HashSet的控制台應用程序。
步驟2:在Program.cs的Main()方法中,添加以下代碼
using
System;
using
System.Collections.Generic;
namespace
CS_Using_HashSet
{
class
Program
{
static
void
Main(
string
[] args)
{
Console.WriteLine(
"Using HashSet"
);
//1. Defining String Array (Note that the string "mahesh" is repeated)
string
[] names =
new
string
[] {
"mahesh"
,
"vikram"
,
"mahesh"
,
"mayur"
,
"suprotim"
,
"saket"
,
"manish"
};
//2. Length of Array and Printing array
Console.WriteLine(
"Length of Array "
+ names.Length);
Console.WriteLine();
Console.WriteLine(
"The Data in Array"
);
foreach
(var n
in
names)
{
Console.WriteLine(n);
}
Console.WriteLine();
//3. Defining HashSet by passing an Array of string to it
HashSet<
string
> hSet =
new
HashSet<
string
>(names);
//4. Count of Elements in HashSet
Console.WriteLine(
"Count of Data in HashSet "
+ hSet.Count);
Console.WriteLine();
//5. Printing Data in HashSet, this will eliminate duplication of "mahesh"
Console.WriteLine(
"Data in HashSet"
);
foreach
(var n
in
hSet)
{
Console.WriteLine(n);
}
Console.ReadLine();
}
}
}
|
上述代碼具有以下規格(注:代碼中的注釋號與以下編號相符)
1.聲明一個名稱名稱的字符串數組,它在其中存儲名稱。該數組具有字符串“mahesh”的重復條目。
2.打印其中的數組長度和數據。
3.定義一個類型為字符串的HashSet 。該對象使用數組進行初始化,該數組自動從數組中添加HashSet中的項。
4.如第1節所述,HashSet對象不允許重復輸入,因此結果將顯示HashSet中存在的數據的計數小於數組計數。
5.在HashSet中顯示數據。
運行應用程序,並顯示以下結果:
第3節:使用UnionWith()方法修改HashSet
UnionWith()方法用於修改HashSet,以包含其中存在的所有元素以及與其建立聯合的其他(IEnumerable)集合中的元素。
以下代碼是UnionWith()上的實現。
步驟1:在項目的Main()方法中添加以下代碼。
string
[] names1 =
new
string
[] {
"mahesh"
,
"sabnis"
,
"manish"
,
"sharma"
,
"saket"
,
"karnik"
};
string
[] Names2 =
new
string
[] {
"suprotim"
,
"agarwal"
,
"vikram"
,
"pendse"
,
"mahesh"
,
"mitkari"
};
//2.
HashSet<
string
> hSetN1 =
new
HashSet<
string
>(Names1);
Console.WriteLine(
"Data in First HashSet"
);
foreach
(var n
in
hSetN1)
{
Console.WriteLine(n);
}
Console.WriteLine(
"_______________________________________________________________"
);
HashSet<
string
> hSetN2 =
new
HashSet<
string
>(names2);
Console.WriteLine(
"Data in Second HashSet"
);
foreach
(var n
in
hSetN2)
{
Console.WriteLine(n);
}
Console.WriteLine(
"________________________________________________________________"
);
//3.
Console.WriteLine(
"Data After Union"
);
hSetN1.UnionWith(hSetN2);
foreach
(var n
in
hSetN1)
{
Console.WriteLine(n);
}
|
以上代碼具有以下規格(注:以下編號與注釋相符)。
數組對象聲明Name1和Names2,其中包含字符串數據。
2.本步驟定義了兩個HashSet的對象hSetN1和hSetN2基於names1和names2分別和來自兩個HashSet的數據被打印。
此步驟在hSetN1上調用UnionWith()方法,並將hSetN2 對象傳遞給它,並在union之后顯示hSetN1中的所有數據。
運行應用程序,將顯示以下結果:
第4節:使用ExceptWith()方法修改哈希集
該方法用於通過刪除與其他集合中的元素匹配的所有元素來修改HashSet。
步驟1:在Main()方法中添加以下代碼。代碼使用第3節中聲明的hSetN2,並使用names1數組聲明一個新的HashSet,該數組用於聲明hSetN1。
Console.WriteLine();
Console.WriteLine(
"_________________________________"
);
Console.WriteLine(
"Data in HashSet before using Except With"
);
Console.WriteLine(
"_________________________________"
);
//storing data of hSetN3 in temporary HashSet
HashSet<
string
> hSetN3 =
new
HashSet<
string
>(names1);
foreach
(var n
in
hSetN3)
{
Console.WriteLine(n);
}
Console.WriteLine();
Console.WriteLine(
"_________________________________"
);
Console.WriteLine(
"Using Except With"
);
Console.WriteLine(
"_________________________________"
);
hSetN3.ExceptWith(hSetN2);
foreach
(var n
in
hSetN3)
{
Console.WriteLine(n);
}
|
運行應用程序后,將顯示以下結果:
上述結果表明,當通過將hSetN2參數傳遞給hSetN2 HashSet的ExceptWith()方法時,從hSetN3中刪除匹配的字符串“mahesh”,並顯示剩余的字符串。
第5節:使用 SymmetricExceptWith()方法修改Hashset
此方法修改HashSet對象以包含僅存在於兩個集合之一中的那些元素,但不能同時包含兩個。
所有匹配的元素將被刪除。
步驟1:在Main()方法中添加以下代碼。代碼useshSetN2在第3節中聲明,並使用數組names1聲明一個新的HashSet hSet4。
HashSet<
string
> hSetN4 =
new
HashSet<
string
>(names1);
Console.WriteLine(
"_________________________________"
);
Console.WriteLine(
"Elements in HashSet before using SymmetricExceptWith"
);
Console.WriteLine(
"_________________________________"
);
Console.WriteLine(
"HashSet 1"
);
foreach
(var n
in
hSetN4)
{
Console.WriteLine(n);
}
Console.WriteLine(
"HashSet 2"
);
foreach
(var n
in
hSetN2)
{
Console.WriteLine(n);
}
Console.WriteLine(
"_________________________________"
);
Console.WriteLine(
"Using SymmetricExceptWith"
);
Console.WriteLine(
"_________________________________"
);
hSetN4.SymmetricExceptWith(hSetN2);
foreach
(var n
in
hSetN4)
{
Console.WriteLine(n);
}
|
通過將hSetN2 HashSet傳遞給它,在HSetN4 HashSet上調用SymmetircExceptWith()方法。這兩個HashSets都包含一個字符串名稱“mahesh”。
通過消除匹配的條目,hSetN4將與hSetN2的值合並。運行應用程序后,結果如下:
第6節:檢查HashSet vs List上的添加,刪除,包含操作的性能。
以上所有部分都介紹了HashSet的各種方法。
但是,當開發人員想要根據性能選擇最合適的集合類型作出決定時,重要的是要檢查哪些操作經常在集合上執行。
通常,添加,刪除,包含是對內存中集合執行的操作。要執行List和HashSet之間的添加,刪除和包含操作的比較,使用以下字符串數組。(注:您可以使用任何其他數據)
static
string
[] names =
new
string
[] {
"Tejas"
,
"Mahesh"
,
"Ramesh"
,
"Ram"
,
"GundaRam"
,
"Sabnis"
,
"Leena"
,
"Neema"
,
"Sita"
,
"Tejas"
,
"Mahesh"
,
"Ramesh"
,
"Ram"
,
"GundaRam"
,
"Sabnis"
,
"Leena"
,
"Neema"
,
"Sita"
,
"Tejas"
,
"Mahesh"
,
"Ramesh"
,
"Ram"
,
"GundaRam"
,
"Sabnis"
,
"Leena"
,
"Neema"
,
"Sita"
,
"Tejas"
,
"Mahesh"
,
"Ramesh"
,
"Ram"
,
"GundaRam"
,
"Sabnis"
,
"Leena"
,
"Neema"
,
"Sita"
,
"Tejas"
,
"Mahesh"
,
"Ramesh"
,
"Ram"
,
"GundaRam"
,
"Sabnis"
, …… };
|
(字符串總數為:550)
將以下方法添加到Program.cs
static
void
Get_Add_Performance_HashSet_vs_List()
{
Console.WriteLine(
"____________________________________"
);
Console.WriteLine(
"List Performance while Adding Item"
);
Console.WriteLine();
List<
string
> lstNames =
new
List<
string
>();
var s2 = Stopwatch.StartNew();
foreach
(
string
s
in
names)
{
lstNames.Add(s);
}
s2.Stop();
Console.WriteLine(s2.Elapsed.TotalMilliseconds.ToString(
"0.000 ms"
)); Console.WriteLine();
Console.WriteLine(
"Ends Here"
);
Console.WriteLine();
Console.WriteLine(
"____________________________________"
);
Console.WriteLine(
"HashSet Performance while Adding Item"
);
Console.WriteLine();
HashSet<
string
> hStringNames =
new
HashSet<
string
>(StringComparer.Ordinal);
var s1 = Stopwatch.StartNew();
foreach
(
string
s
in
names)
{
hStringNames.Add(s);
}
s1.Stop();
Console.WriteLine(s1.Elapsed.TotalMilliseconds.ToString(
"0.000 ms"
)); Console.WriteLine();
Console.WriteLine(
"Ends Here"
);
Console.WriteLine(
"____________________________________"
);
Console.WriteLine();
}
|
HashSet vs List - Add()方法
上述方法通過從名稱數組中迭代字符串對List和HashSet執行Add()操作。
操作的性能是通過計算秒表從類System.Diagnostics程序命名空間。
運行應用程序,並顯示以下結果:
請注意,下面的結果顯示了時間差我的機器,它可以執行樣本時,您的計算機上有所不同。
與HashSet相比,List <>花費更少的時間來添加字符串。
原因之一是List.Add()只是將一個項目添加到列表,而HashSet.Add()將跳過新項目(如果它等於其中一個現有項目)。與List.Add()方法相比,這需要時間來執行HashSet.Add()方法。
HashSet vs List - Contains()方法
在Program.cs中添加以下方法
static
void
Get_Contains_Performance_HashSet_vs_List()
{
Console.WriteLine(
"____________________________________"
);
Console.WriteLine(
"List Performance while checking Contains operation"
);
Console.WriteLine();
List<
string
> lstNames =
new
List<
string
>();
var s2 = Stopwatch.StartNew();
foreach
(
string
s
in
names)
{
lstNames.Contains(s);
}
s2.Stop();
Console.WriteLine(s2.Elapsed.TotalMilliseconds.ToString(
"0.000 ms"
)); Console.WriteLine();
Console.WriteLine(
"Ends Here"
);
Console.WriteLine();
Console.WriteLine(
"____________________________________"
);
Console.WriteLine(
"HashSet Performance while checking Contains operation"
);
Console.WriteLine();
HashSet<
string
> hStringNames =
new
HashSet<
string
>(StringComparer.Ordinal);
var s1 = Stopwatch.StartNew();
foreach
(
string
s
in
names)
{
hStringNames.Contains(s);
}
s1.Stop();
Console.WriteLine(s1.Elapsed.TotalMilliseconds.ToString(
"0.000 ms"
));
Console.WriteLine();
Console.WriteLine(
"Ends Here"
);
Console.WriteLine(
"____________________________________"
);
Console.WriteLine();
}
|
上述方法檢查List和HashSet是否包含作為輸入參數傳遞給Contains()方法的項。運行應用程序,結果將顯示如下圖所示
結果清楚地表明,HashSet提供了比List更快的查找元素。
這是因為HashSet中沒有重復的數據。HashSet為其中的每個項目維護哈希,並將它們排列在單獨的桶中,其中包含存儲在HashSet中的項目的每個字符的散列。
當查找發生時,HashSet會將其從第一個字符開始進行散列並將其跳轉到匹配的每個字符,並從HashSet中提取元素。
HashSet vs List - Remove()方法
在Program.cs中添加以下方法
static
void
Get_Remove_Performance_HashSet_vs_List()
{
Console.WriteLine(
"____________________________________"
);
Console.WriteLine(
"List Performance while performing Remove item operation"
);
Console.WriteLine();
List<
string
> lstNames =
new
List<
string
>();
var s2 = Stopwatch.StartNew();
foreach
(
string
s
in
names)
{
lstNames.Remove(s);
}
s2.Stop();
Console.WriteLine(s2.Elapsed.TotalMilliseconds.ToString(
"0.000 ms"
)); Console.WriteLine();
Console.WriteLine(
"Ends Here"
);
Console.WriteLine();
Console.WriteLine(
"____________________________________"
);
Console.WriteLine(
"HashSet Performance while performing Remove item operation"
);
Console.WriteLine();
HashSet<
string
> hStringNames =
new
HashSet<
string
>(StringComparer.Ordinal);
var s1 = Stopwatch.StartNew();
foreach
(
string
s
in
names)
{
hStringNames.Remove(s);
}
s1.Stop();
Console.WriteLine(s1.Elapsed.TotalMilliseconds.ToString(
"0.000 ms"
)); Console.WriteLine();
Console.WriteLine(
"Ends Here"
);
Console.WriteLine(
"____________________________________"
);
Console.WriteLine();
}
|
上述方法使用Remove()方法執行List和HashSet上的刪除操作。運行應用程序,結果將顯示如下圖所示:
上圖清楚地顯示了HashSet的刪除操作比List更快。“刪除”操作也與“包含”操作類似。