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”]。