定义:什么是HashSet?


420

HashSet .NET Framework 3.5中引入了C#HashSet数据结构。可以在HashSet MSDN页面上找到已实现成员的完整列表。

  1. 在哪里使用?
  2. 您为什么要使用它?



它在内部使用哈希表。如果您具有良好的哈希表实现(例如Dictionary <T>),则可以轻松地自己实现HashSet。
Raz Megrelidze 2015年

Answers:


614
    1. A可以HashSet容纳一组对象,但是可以让您轻松快速地确定对象是否已经存在于该对象集中。它是通过内部管理数组并使用从对象的哈希码计算出的索引来存储对象来实现的。在这里看看

    2. HashSet是包含唯一元素的无序集合。它具有标准的收集,添加,删除,包含操作,但是由于它使用基于哈希的实现,因此这些操作为O(1)。(例如,与List相反,对于Contains和Remove,它是O(n)。)HashSet还提供了标准的集合操作,例如unionintersection对称差分在这里看看

  1. 集合有不同的实现。有些通过散列元素使插入和查找操作变得超级快。但是,这意味着添加元素的顺序丢失了。其他实现则以增加的运行时间为代价来保留添加的订单。

HashSetC#中的类采用第一种方法,因此保留元素的顺序。它比常规的要快得多List。一些基本的基准测试表明,在处理主要类型(int,double,bool等)时,HashSet的速度更快。使用类对象时,它快得多。这就是说HashSet很快。

唯一HashSet要注意的是索引无法访问。要访问元素,您可以使用枚举器,也可以使用内置函数将转换HashSet为,List然后进行迭代。在这里看看


13
哈希集和类似的两件事是.NET,而不是C#。HashSet也不保留顺序。尝试从哈希集合添加和删除项目,你就会知道,如果你以后..迭代
nawfal

13

HashSet具有内部结构(散列),其中物品可以被搜索,并迅速识别。缺点是迭代HashSet(或通过索引获取项目)相当慢。

那么,为什么有人想要知道某个条目是否已经存在于集合中?

a HashSet有用的一种情况是从可能存在重复项的列表中获取不同的值。将项目添加到后,即可HashSet快速确定该项目是否存在(Contains运算符)。

另一优点HashSet是设置操作: IntersectWithIsSubsetOfIsSupersetOfOverlapsSymmetricExceptWithUnionWith

如果您熟悉对象约束语言,那么您将识别这些设置操作。您还将看到,它距离可执行UML的实现又近了一步。


20
回复:缺点。不,通过HashSet进行迭代非常快。其次,不可能通过索引获取项目。实际上,元素是无序存储的。
Nigel Touch

@Nigel Touch。如果您不关心索引(添加索引的顺序),则迭代速度很快。但是,如果您担心索引,则必须将索引与每个哈希键一起存储,因此它可能会很慢,因为必须穷举搜索列表以检索正确的项。此行为与列表中的项有很大不同,在列表中,项是按照添加顺序进行索引的。
2014年

之所以会如此之快是有道理的,因为没有两个哈希是相同的。使查询能够利用“短路”方法,快速排除某些条件。
Chef_Code

8

简而言之,在不透露厨房秘密的情况下: 通常,集合是一个不包含重复元素且其元素没有特定顺序的集合。因此,A HashSet<T>与泛型类似List<T>,但为快速查找(通过顾名思义,通过哈希表)进行了优化,但代价是失去了顺序。


1
但是HashSet <T>是否可以存储两个具有相同数据的对象,例如两个具有相同属性且具有相同内容的Product类?
约翰·赫斯塔德

我想我们永远不会知道
Denny

@JohanHerstad假设您的类的EqualityComparer关心这些属性,或者使用关心这些属性的IEqualityComparer构造HashSet,我不明白为什么不这样做。HashSet文档清楚地表明,它依靠一个或另一个来确定唯一性。
培根咬碎了

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.