(轉) C#解惑:HashSet


HashSet<T>是一個相對“冷門”的類型,平時在項目中用得不多,但是在特定的業務中可以大用。

先來了解下HashSet<T>類,主要被設計用來存儲集合,做高性能集運算,例如兩個集合求交集、並集、差集等。從名稱可以看出,它是基於Hash的,可以簡單理解為沒有Value的Dictionary。

HashSet<T>不能用索引訪問,不能存儲重復數據,元素T必須正確實現了EqualsGetHashCode

HashSet<T>的一些特性如下:

  1. HashSet<T>中的值不能重復且沒有順序。
  2. HashSet<T>的容量會按需自動添加。

HashSet<T>的優勢和與List<T>的比較

HashSet<T>最大的優勢是檢索的性能,簡單的說它的Contains方法的性能在大數據量時比List<T>好得多。曾經做過一個測試,將800W條int類型放在List<int>集合中,使用Contains判斷是否存在,速度巨慢,而放在HashSet<int>性能得到大幅提升。

在內部算法實現上,HashSet<T>的Contains方法復雜度是O(1),List<T>的Contains方法復雜度是O(n),后者數據量越大速度越慢,而HashSet<T>不受數據量的影響。

所以在集合的目的是為了檢索的情況下,我們應該使用HashSet<T>代替List<T>。比如一個存儲關鍵字的集合,運行的時候通過其Contains方法檢查輸入字符串是否關鍵字。

在3.5之前,想用哈希表來提高集合的查詢效率,只有Hashtable和Dictionary兩種選擇,而這兩種都是鍵-值方式的存儲。但有些時候,我們只需要其中一個值,例如一個Email集合,如果用泛型哈希表來存儲,往往要在Key和Value各保存一次,不可避免的要造成內存浪費。而HashSet只保存一個值,更加適合處理這種情況。

此外,HashSet的Add方法返回bool值,在添加數據時,如果發現集合中已經存在,則忽略這次操作,並返回false值。而Hashtable和Dictionary碰到重復添加的情況會直接拋出錯誤。

從使用上來看,HashSet和線性集合List更相似一些,但前者的查詢效率有着極大的優勢。假如,用戶注冊時輸入郵箱要檢查唯一性,而當前已注冊的郵箱數量達到10萬條,如果使用List進行查詢,需要遍歷一次列表,時間復雜度為O(n),而使用HashSet則不需要遍歷,通過哈希算法直接得到列表中是否已存在,時間復雜度為O(1),這是哈希表的查詢優勢。

和List的區別

HashSet是Set集合,它只實現了ICollection接口,在單獨元素訪問上,有很大的限制:

跟List相比,不能使用下標來訪問元素,如:list[1] 。

跟Dictionary相比,不能通過鍵值來訪問元素,例如:dic[key],因為HashSet每條數據只保存一項,並不采用Key-Value的方式,換句話說,HashSet中的Key就是Value,假如已經知道了Key,也沒必要再查詢去獲取Value,需要做的只是檢查值是否已存在。

所以剩下的僅僅是開頭提到的集合操作,這是它的缺點,也是特點。

集合運算

IntersectWith (IEnumerable other) (交集)

  1.  
    public void IntersectWithTest()
  2.  
    {
  3.  
    HashSet< int> set1 = new HashSet<int>() { 1, 2, 3 };
  4.  
    HashSet< int> set2 = new HashSet<int>() { 2, 3, 4 };
  5.  
     
  6.  
    set1.IntersectWith(set2);
  7.  
     
  8.  
    foreach (var item in set1)
  9.  
    {
  10.  
    Console.WriteLine(item);
  11.  
    }
  12.  
     
  13.  
    //輸出:2,3
  14.  
    }

UnionWith (IEnumerable other) (並集)

public void UnionWithTest()
{
HashSet set1 = new HashSet() { 1, 2, 3 };
HashSet set2 = new HashSet() { 2, 3, 4 };

  1.  
    set1.UnionWith(set2);
  2.  
     
  3.  
    foreach (var item in set1)
  4.  
    {
  5.  
    Console.WriteLine(item);
  6.  
    }
  7.  
     
  8.  
    //輸出:1,2,3,4
  9.  
    }

ExceptWith (IEnumerable other) (排除)

public void ExceptWithTest()
{
HashSet set1 = new HashSet() { 1, 2, 3 };
HashSet set2 = new HashSet() { 2, 3, 4 };

  1.  
    set1.ExceptWith(set2);
  2.  
     
  3.  
    foreach (var item in set1)
  4.  
    {
  5.  
    Console.WriteLine(item);
  6.  
    }
  7.  
     
  8.  
    //輸出:1
  9.  
    }
原貼: https://blog.csdn.net/X_X_OO/article/details/52529548


免責聲明!

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



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