HashSet是否保留插入顺序?

在.NET 3.5中引入的HashSet集合在使用foreach迭代时是否保留了插入顺序?

该文档指出,该集合没有sorting,但它没有说任何关于插入顺序。 BCL的预发布博客条目指出,它是无序的,但本文指出,它旨在保持插入顺序。 我有限的testing表明,这个顺序是保存的,但这可能是巧合。

这个HashSet MSDN页面特别说:

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

我认为保留订单的文章显然是错误的。 对于简单的testing来说,由于内部结构的原因,插入顺序可能会得到很好的保留,但是不能保证,也不会总是这样工作。 我会尝试拿出一个反例。

编辑:这是反例:

 using System; using System.Collections.Generic; class Test { static void Main() { var set = new HashSet<int>(); set.Add(1); set.Add(2); set.Add(3); set.Remove(2); set.Add(4); foreach (int x in set) { Console.WriteLine(x); } } } 

尽pipe在4之前插入了3,但是打印了1,4,3。

如果您不删除任何项目,则可能会保留广告订单。 我不确定,但我不会完全惊讶。 不过,我认为依靠这一点将是一个非常糟糕的主意:

  • 它没有被logging为以这种方式工作,文档明确指出它没有sorting。
  • 我没有看到内部结构或源代码(显然我没有),我必须仔细研究它们,然后才能以坚定的态度提出这样的要求。
  • 实现可以非常容易地在框架的版本之间改变。 依靠这个就像依靠string.GetHashCode实现不会改变 – 有些人在.NET 1.1的时候做了回来,然后当.NET 2.0中的实现发生变化的时候被烧毁了。

该文件指出:

HashSet <(Of <(T>)>)集合没有sorting,也不能包含重复的元素。 如果顺序或元素重复比应用程序的性能更重要,请考虑将List <(Of <(T>)>)类与Sort方法一起使用。

因此,它是否实际上保留了当前实现中的元素的顺序并不重要,因为它没有被logging为这样,即使现在看来这可能在将来的任何时候改变(即使在一个修补程序框架)。

您应该根据logging的合同进行编程,而不是实施细节

不,散列集不会保留插入顺序,至less不可预测。 您可以使用LinkedHashSet(Java)或等效的方法。 LinkedHashSet将保持顺序。

如果你想要订单,你甚至不应该在一开始就使用一套 …它不是有序的元素,除非在特殊情况下。

编辑:听起来像我讲道: – /对不起。

.NET4中特别有一个SortedSet<T>集合 。

这会给你sorting,但不太可能是插入顺序sorting。 既然你可以使用一个自定义的IComparer ,理论上你可以做任何事情。

读取HashSet.AddIfNotPresent的源代码,您可以看到假定没有任何删除操作,保留了插入顺序。

因此, new HashSet<string> { "Tom", "Dick", "Harry" }保留顺序,但是如果你删除了Dick并添加了Rick,顺序将是[“Tom”,“Rick”,“Harry”]。