使用foreach
进行迭代时,.NET 3.5中引入的HashSet
集合是否会保留插入顺序?
documentation表示集合未排序,但没有说明插入顺序。预发行版BCL blog entry表示它是无序的,但this article声明它旨在保留广告订单。我的有限测试表明,该顺序得以保留,但这可能是巧合。
答案 0 :(得分:67)
集合是一个不包含重复元素的集合,其元素没有特定的顺序。
答案 1 :(得分:39)
我认为声称它保留排序的文章是完全错误的。对于简单的测试,由于内部结构,插入顺序可能会得到很好的保留,但是不能保证,并且不会总是以这种方式工作。我会尝试提出一个反例。
编辑:这是反例:
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);
}
}
}
尽管在4之前插入了3个,但仍会打印1,4,3。
可能如果你永远不会删除任何项目,它将保留插入顺序。我不确定,但我不会完全惊讶。但是,我认为依靠它是一个非常糟糕的主意:
string.GetHashCode
实现不会改变 - 有些人在.NET 1.1天中做过,然后当实现 在.NET中发生变化时它们就被烧毁了2.0 ... 答案 2 :(得分:7)
文档说明:
HashSet&lt;(Of&lt;(T&gt;)&gt;)集合未排序且不能包含重复元素。如果订单或元素重复比应用程序的性能更重要,请考虑使用List&lt;(&lt;(T&gt;)&gt;)类和Sort方法。
因此,它是否实际上保留了当前实现中元素的顺序并不重要,因为它没有记录为这样做,即使它现在看起来可能会在未来的任何时候发生变化(即使在框架的修补程序。)
您应该针对记录的合同编程,而不是实施细节。
答案 3 :(得分:2)
不,哈希集不会保留插入顺序,至少不能预测。您可以使用LinkedHashSet(Java)或等效项。 LinkedHashSet将保留订单。
如果你想要订单,你甚至不应该首先使用一套 ...它不是为有序元素制作的,除非在特殊情况下。
答案 4 :(得分:2)
特别是SortedSet<T>
collection in .NET4。
这会给你排序,但不太可能是插入顺序排序。由于您可以使用自定义IComparer
,理论上您可以执行此操作。
答案 5 :(得分:0)
阅读here的源代码,您可以看到保留插入顺序,假设没有任何删除。
因此new HashSet<string> { "Tom", "Dick", "Harry" }
会保留顺序,但如果您删除Dick并添加Rick,则顺序为[“Tom”,“Rick”,“Harry”]。