代码之家  ›  专栏  ›  技术社区  ›  Brian Rasmussen

HashSet是否保留插入顺序?

  •  55
  • Brian Rasmussen  · 技术社区  · 17 年前

    是吗 HashSet NET 3.5中引入的集合在使用 foreach

    这个 documentation 声明集合未排序,但它没有说明任何有关插入顺序的内容。预释放BCL blog entry 声明它是无序的,但是 this article

    6 回复  |  直到 10 年前
        1
  •  85
  •   Michael Burr    17 年前
        2
  •  46
  •   Jon Skeet    17 年前

    我认为那篇声称它保留了秩序的文章是完全错误的。对于简单的测试,由于内部结构的原因,插入顺序可能会得到很好的保留,但这并不能保证,也不能总是这样工作。我会试着想出一个反例。

    编辑:以下是反例:

    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);
            }
        }
    }
    

    可能的 如果您从未删除任何项目,它将保留插入顺序。我不确定,但我不会完全感到惊讶。然而,我认为依靠这一点是一个非常糟糕的想法:

    • 文件中没有说明它是以这种方式工作的,文件中明确指出它没有排序。
    • 实现可以很容易地在框架的不同版本之间进行更改。依靠这一点就像依靠 string.GetHashCode .NET2.0中的更改。。。
        3
  •  7
  •   Greg Beech    17 年前

    哈希集<(Of<(T>)>)集合未排序,不能包含重复的元素。如果应用程序的顺序或元素重复比性能更重要,请考虑使用列表& lt;(属于<(T>)>)类以及排序方法。

    因此,它是否在当前实现中实际保留了元素的顺序并不重要,因为它没有这样做的文档记录,即使它现在看起来是这样,这在将来的任何时候都可能发生变化(即使在框架的热修复中)。

    书面合同 实施细节

        4
  •  3
  •   Chris Marisic    14 年前

    特别是有一个 SortedSet<T> collection in .NET4 .

    这将为您提供排序,但不太可能是插入顺序排序。因为您可以使用自定义 IComparer 理论上你可以让它做任何事。

        5
  •  2
  •   Sudhir Jonathan    17 年前

    不,哈希集不会保留插入顺序,至少不可预测。您可以使用LinkedHashSet(Java)或等效工具。LinkedHashSet将保持秩序。

    如果你想要订单,你甚至不应该一开始就使用一套 ... 除特殊情况外,它不适用于有序元素。

        6
  •  2
  •   Colonel Panic    10 年前

    正在阅读的源代码 HashSet.AddIfNotPresent 假设没有任何删除 .

    因此 new HashSet<string> { "Tom", "Dick", "Harry" } 保留顺序,但如果您删除迪克并添加里克,则顺序将为[“汤姆”、“里克”、“哈利”]。

    推荐文章