• (转) C#解惑:HashSet<T>类


    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
  • 相关阅读:
    深(爆)搜专题整理
    牛客CSP-S提高组赛前集训营1 T2:乃爱与城市拥挤程度
    [BZOJ3743][Coci2015]Kamp 题解
    CSP2019-S,J初赛游记
    指针复习
    二叉树复习
    最短路复习
    数据库关联查询与模型之间的关联
    数据库操作Flask-SQLAlchemy之模型声明及数据库表的生成与删除
    csrf攻击防范
  • 原文地址:https://www.cnblogs.com/refuge/p/9465466.html
Copyright © 2020-2023  润新知