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

(转) C#解惑:HashSet<T>类的更多相关文章

  1. C#解惑:HashSet<T>类

    原贴: https://blog.csdn.net/X_X_OO/article/details/52529548 https://www.cnblogs.com/refuge/p/9465466.h ...

  2. HashSet<T>类 用法

    HashSet<T>类主要是设计用来做高性能集运算的,例如对两个集合求交集.并集.差集等.集合中包含一组不重复出现且无特性顺序的元素 改变集的值的方法: HashSet<T>的 ...

  3. HashSet<T>类

    HashSet<T>类主要是设计用来做高性能集运算的,例如对两个集合求交集.并集.差集等.集合中包含一组不重复出现且无特性顺序的元素. HashSet<T>的一些特性如下: 1 ...

  4. (转)HashSet<T>类

    转载于:http://www.importnew.com/6931.html HashSet<T>类主要是设计用来做高性能集运算的,例如对两个集合求交集.并集.差集等.集合中包含一组不重复 ...

  5. HashSet 实现类

    HashSet 实现类 通过 HashCode 判断元素是否存在,若存在则不添加,否则添加以此实现唯一性 常用方法 Modifier and Type Method and Description b ...

  6. Java解惑五:类之谜

    本文是依据JAVA解惑这本书,做的笔记.电子书见:http://download.csdn.net/detail/u010378705/7527721 谜题46 函数重载的问题. JAVA重载解析过程 ...

  7. Set接口HashSet实现类

    java.util.Set接口 extends Collection接口 Set特点: 1.不允许有重复的元素 2.没有索引,没有带索引的方法,也不能使用普通的for遍历 java.util.Hash ...

  8. 微软在 .NET 3.5 新增了一个 HashSet 类,在 .NET 4 新增了一个 SortedSet 类,本文介绍他们的特性,并比较他们的异同。

    微软在 .NET 3.5 新增了一个 HashSet 类,在 .NET 4 新增了一个 SortedSet 类,本文介绍他们的特性,并比较他们的异同. .NET Collection 函数库的 Has ...

  9. Nullable类型和HashSet<T>集合

    今天接触到两个新的类型,查了一下才发现它们已经出现好久了,特作一下标记 Nullable结构 在System命名空间下,在 .NET Framework 2.0 版中是新增的:用它定义的值类型的对象与 ...

随机推荐

  1. redux的基本概念

    1. State 应用的数据,即状态 2. Action 一个纯对象,携带这个操作的类型和数据信息,主要是用来进行传递信息,如下所示: const action = { type: 'ADD_TODO ...

  2. 【NOIP模拟赛】藏宝图 最小生成树

    性质:我们把最小生成树建出来,如果其距离符合那么就是对的,不符合就是错的 因为这是个n^2的图所以不能Kruskal只能Prim #include <cstdio> #include &l ...

  3. 使用UMeditor富文本编辑器上传图片

    注:本文系作者原创,但可随意转载. 最近写自己的网站玩儿,写到博客的部分,打算使用UMeditor,因为之前也用过(但是好像没实现图片上传的功能),感觉用起来还比较简单. 不过还是折腾了一下午...遇 ...

  4. mysql_存储过程和函数

    存储过程和函数 1.什么是存储过程和函数 存储过程和函数是事先经过编译并存储在数据库中的一段SQL语句集合,调用存储过程和函数可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对 ...

  5. vm虚拟机 开启时报错 无法打开内核设备“\\.\Global\vmx86”: 系统找不到指定的文件。

    解决办法 方案一 1/http://jingyan.baidu.com/article/455a9950aaf4aea167277878.html 方案二 2.http://jingyan.baidu ...

  6. Idea IntelliJ远程调试教程

    总结 第一步:修改startup.sh 在倒第二行加上export JPDA_ADDRESS=8787 最后一行在start前面加上"   jpda   " 第二步:配置Idea, ...

  7. 百练3383:Cell Phone Network

    传送门:http://bailian.openjudge.cn/practice/3383/ [题解] 题目就是最小支配集. 学习了最小支配集的解法: 树形dp(有空可以推一推) 贪心:DFS遍历后逆 ...

  8. codevs1163访问艺术馆 树形dp

    算裸的树形dp吧 回来复习一波 #include<cstdio> #include<cstring> #include<algorithm> #include< ...

  9. bzoj1499: [NOI2005]瑰丽华尔兹&&codevs1748 单调队列优化dp

    这道题 网上题解还是很多很好的 强烈推荐黄学长 码风真的好看 神犇传送门 学习学习 算是道单调队列优化dp的裸题吧 #include<cstdio> #include<cstring ...

  10. bzoj1503: [NOI2004]郁闷的出纳员 fhqtreap版

    这道题写法和之前差不多 但是fhqtreap在加点的时候为了同时维护大根堆以及二叉排序树的性质所以插入时也要注意分裂 fhqteap需要判断指针是否为空 不然就会re 这个我调了很久 #include ...