了解C#中的HashSet與示例


在C#中引入HashSet

在.NET框架中,有幾個類可用於執行這些操作。一些課程如下:

  • 列表
  • 字典
  • 哈希集
  • 隊列

集合

在C#編程中,像ArrayList,List這樣的集合,只需添加其中的值,而不檢查任何重復。為了避免這種重復的數據存儲,.NET提供集合名稱集。這是一個具有不同項目的集合類型。

有兩種類型的集合,SortedSetHastSet。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的對象hSetN1hSetN2基於names1names2分別和來自兩個HashSet的數據被打印。

此步驟在hSetN1上調用UnionWith()方法,並將hSetN2 對象傳遞給它,並在union之后顯示hSetN1中的所有數據。

運行應用程序,將顯示以下結果:

hashset-unionwith

第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更快。“刪除”操作也與“包含”操作類似。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM