HashSet是否保留了插入顺序?

时间:2009-03-18 07:39:10

标签: .net hashset

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

documentation表示集合未排序,但没有说明插入顺序。预发行版BCL blog entry表示它是无序的,但this article声明它旨在保留广告订单。我的有限测试表明,该顺序得以保留,但这可能是巧合。

6 个答案:

答案 0 :(得分:67)

This HashSet MSDN page具体说:

  

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

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