什么时候应该使用HashSet <T>types?

我正在探索HashSet<T>types,但我不明白它在集合中的位置。

可以用它来代替List<T>吗? 我想HashSet<T>的性能会更好,但是我看不到其元素的单独访问。

仅仅是枚举吗?

关于HashSet<T>的重要之处就在于它的名字:它是一个集合 。 唯一可以做的事情就是确定其成员是什么,并检查一个项目是否是成员。

询问是否可以检索单个元素(例如set[45] )会误解该集合的概念。 没有这样的事情,作为一个集合的第45个元素。 一组中的项目没有sorting。 集合{1,2,3}和{2,3,1}在各方面是相同的,因为它们具有相同的成员资格,并且成员资格是重要的。

迭代HashSet<T>有点危险,因为这样做会对集合中的项目施加一个顺序。 这个命令并不是这个集合的一个属性。 你不应该依赖它。 如果集合中的物品的订购对您来说很重要,那么这个集合不是一个集合。

集合是非常有限的,并与独特的成员。 另一方面,他们真的很快。

下面是我使用HashSet<string>的一个真实例子:

我的UnrealScript文件语法高亮部分是一个突出Doxygen风格的注释的新function。 我需要能够判断@\命令是否有效,以确定是以灰色(有效)还是红色(无效)显示。 我有一个所有有效的命令的HashSet<string> ,所以每当我在词法分析器中打一个@xxx标记,我使用validCommands.Contains(tokenText)作为我的O(1)有效性检查。 我真的不在乎除了有效命令集中命令的存在。 让我们看看我面临的替代scheme:

  • Dictionary<string, ?> :我使用什么types的值? 这个值是没有意义的,因为我只是要使用ContainsKey 。 注意:在.NET 3.0之前,这是O(1)查找的唯一select – 为3.0添加了HashSet<T> ,并对4.0进行了扩展以实现ISet<T>
  • List<string> :如果我保持列表sorting,我可以使用BinarySearch ,它是O(log n)(没有看到上面提到的这个事实)。 然而,由于我的有效命令列表是一个永远不会改变的固定列表,这将永远不会比简单…
  • string[] :同样, Array.BinarySearch给出了O(log n)的性能。 如果名单很短,这可能是performance最佳的select。 它总是比HashSetDictionaryList有更less的空间开销。 即使使用BinarySearch ,大集合也不会更快,但对于小集合来说,这是值得尝试的。 虽然我有几百件东西,所以我通过了这个。

HashSet<T>实现了ICollection<T>接口:

 public interface ICollection<T> : IEnumerable<T>, IEnumerable { // Methods void Add(T item); void Clear(); bool Contains(T item); void CopyTo(T[] array, int arrayIndex); bool Remove(T item); // Properties int Count { get; } bool IsReadOnly { get; } } 

List<T>实现了IList<T> ,它扩展了ICollection<T>

 public interface IList<T> : ICollection<T> { // Methods int IndexOf(T item); void Insert(int index, T item); void RemoveAt(int index); // Properties T this[int index] { get; set; } } 

HashSet已经设置了语义,通过哈希表在内部实现:

集合是不包含重复元素的集合,其元素没有特定的顺序。

如果HashSet失去了索引/位置/列表行为,它会得到什么?

从HashSet添加和检索项目总是由对象本身而不是通过索引器,并且接近O(1)操作(List是O(1)add,O(1)通过索引检索O(n)find /去掉)。

一个HashSet的行为可以通过添加/删除键作为值来比较使用Dictionary<TKey,TValue> ,并忽略字典值本身。 您会希望字典中的键不会有重复的值,这就是“设置”部分的重点。

性能将是一个糟糕的理由selectHashSet而不是List。 相反,什么更好地捕捉你的意图? 如果顺序很重要,那么Set(或HashSet)就出来了。 如果重复,也是如此。 但是当我们不关心订单的时候,我们有很多情况,我们宁愿不要重复 – 那就是当你想要一个集合时。

HashSet是由散列实现的一个集合 。 一个集合是不包含重复元素的值的集合。 一组中的值通常也是无序的。 所以不,一个集合不能用来replace一个列表(除非你首先使用一个集合)。

如果你想知道什么样的设置可能是好的:显然,你想摆脱重复的地方。 作为一个稍微做作的例子,假设你有一个软件项目的10.000版本的列表,你想知道有多less人为这个项目做出了贡献。 您可以使用Set<string>并遍历修订列表,并将每个修订版本的作者添加到集合中。 一旦你完成了迭代,集合的大小就是你正在寻找的答案。

哈希集合最常见的用途是查看它们是否包含某个元素,它接近于O(1)操作(假设一个足够强的哈希函数),而不是包含检查的列表是O( n)(以及它是O(log n)的sorting集)。 所以,如果你做了很多检查,某个项目是否包含在某个列表中,则可能会提高性能。 如果你只是遍历它们,那么不会有太大的区别(遍历整个集合是O(n),与列表相同,并且在添加项目时,哈希集合有更多的开销)。

不,你不能索引一套,因为套不是有序的,所以无论如何也没有意义。 如果你添加一些项目,设置将不会记得哪一个是第一个,哪个第二等。

HashSet将用于删除IEnumerble集合中的重复元素。 例如,

 List<string> duplicatedEnumrableStrings = new List<string> {"abc", "ghjr", "abc", "abc", "yre", "obm", "ghir", "qwrt", "abc", "vyeu"}; HashSet<string> uniqueStrings = new HashSet(duplicatedEnumrableStrings); 

在这些代码运行后,uniqueStrings会保存{“abc”,“ghjr”,“yre”,“obm”,“qwrt”,“vyeu”};

List<T>用于存储有序的信息集合。 如果您知道列表元素的相对顺序,则可以在一段时间内访问它们。 但是,要确定元素在列表中的位置或者检查它是否存在于列表中,查找时间是线性的。 另一方面, HashedSet<T>不保证存储数据的顺序,因此为其元素提供了不断的访问时间。

顾名思义, HashedSet<T>是一个实现集合语义的数据结构。 数据结构被优化以实现集合操作(​​即联合,差异,相交),这不能像传统的List实现那样有效地完成。

因此,select使用哪种数据types取决于您正在尝试使用哪种数据types。 如果你不关心你的元素是如何在一个集合中进行sorting的,而只是想要检查是否存在,请使用HashSet<T> 。 否则,请考虑使用List<T>或其他合适的数据结构。

HashSet<T>是.NET框架中的一种数据结构,能够将math集合表示为对象。 在这种情况下,它使用哈希码(每个项目的GetHashCode结果)来比较设置元素的相等性。

一个集合与一个列表的不同之处在于,它只允许在其中包含相同元素的一次出现。 如果尝试添加第二个相同的元素, HashSet<T>将仅返回false 。 事实上,查找元素非常快( O(1)时间),因为内部数据结构只是一个哈希表。

如果您想知道要使用哪一个,请注意,使用List<T>其中HashSet<T>适用)不是最大的错误,尽pipe它可能会允许在您的集合中存在不需要的重复项目的问题。 更重要的是,查找(项目检索)效率要高得多 – 理想的情况是O(1) (用于完美的分包)而不是O(n)时间 – 这在很多情况下非常重要。

简而言之 – 无论何时你想使用一个字典(或一个字典,其中S是T的一个属性),那么你应该考虑一个HashSet(或HashSet +在T上实现IEquatable,这相当于S)