.net HashSet 是否保留插入顺序?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/657263/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Does HashSet preserve insertion order?
提问by Brian Rasmussen
Does the HashSetcollection introduced in .NET 3.5 preserve insertion order when iterated using foreach?
HashSet.NET 3.5 中引入的集合在使用 迭代时是否保留插入顺序foreach?
The documentationstates, that the collection is not sorted, but it doesn't say anything about insertion order. A pre-release BCL blog entrystates that it is unordered, but this articlestates that it is designed to preserve insertion order. My limited testing suggests, that order is preserved, but that could be a coincidence.
该文档的状态,该集合没有排序,但它并没有说明插入顺序什么。一个预发布的 BCL博客条目声明它是无序的,但这篇文章声明它旨在保留插入顺序。我有限的测试表明,该顺序被保留,但这可能是巧合。
回答by Michael Burr
This HashSet MSDN pagespecifically says:
这个 HashSet MSDN 页面特别说明:
A set is a collection that contains no duplicate elements, and whose elements are in no particular order.
集合是不包含重复元素且其元素没有特定顺序的集合。
回答by Jon Skeet
I think the article claiming it preserves ordering is just plain wrong. For simple tests the insertion order may well be preserved due to the internal structure, but it's not guaranteed and won't always work that way. I'll try to come up with a counterexample.
我认为声称它保留排序的文章完全是错误的。对于简单的测试,由于内部结构,插入顺序可能会很好地保留下来,但不能保证并且不会总是那样工作。我会试着想出一个反例。
EDIT: Here's the counterexample:
编辑:这是反例:
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);
}
}
}
This prints 1, 4, 3 despite 3 having been inserted before 4.
尽管在 4 之前插入了 3,但仍会打印 1, 4, 3。
It's possiblethat if you never remove any items, it will preserve insertion order. I'm not sure, but I wouldn't be entirely surprised. However, I think it would be a very bad idea to rely on that:
这是可能的,如果你从来没有删除任何项目,它将保留插入顺序。我不确定,但我不会完全感到惊讶。但是,我认为依赖它是一个非常糟糕的主意:
- It's not documented to work that way, and the documentation explicitly states that it's not sorted.
- I haven't looked at the internal structures or source code (which I don't have, obviously) - I'd have to study them carefully before making any such claim in a firm manner.
- The implementation could very easily change between versions of the framework. Relying on this would be like relying on the
string.GetHashCodeimplementation not changing - which some people did back in the .NET 1.1 days, and then they got burned when the implementation didchange in .NET 2.0...
- 它没有记录以这种方式工作,并且文档明确指出它没有排序。
- 我没有查看内部结构或源代码(显然我没有) - 在以坚定的方式提出任何此类声明之前,我必须仔细研究它们。
- 实现可以很容易地在框架的版本之间改变。依托这就像依靠
string.GetHashCode不改变执行-这部分人确实早在NET 1.1天,然后在执行他们得到了焚烧确实在.NET 2.0的变化...
回答by Greg Beech
The documentation states:
该文件指出:
A HashSet<(Of <(T>)>) collection is not sorted and cannot contain duplicate elements. If order or element duplication is more important than performance for your application, consider using the List<(Of <(T>)>) class together with the Sort method.
HashSet<(Of <(T>)>) 集合未排序且不能包含重复元素。如果顺序或元素重复对于您的应用程序来说比性能更重要,请考虑将 List<(Of <(T>)>) 类与 Sort 方法一起使用。
Therefore it doesn't matter whether it actually preserves the order of elements in the current implementation, because it is not documented as doing so, and even if it appears to now this may change at any point in the future (even in a hotfix to the framework).
因此,它是否真的保留了当前实现中元素的顺序并不重要,因为它没有被记录为这样做,即使现在看起来这可能会在未来的任何时候改变(即使在一个修补程序中框架)。
You should be programming against documented contracts, not implementation details.
您应该针对文档化的契约而不是实现细节进行编程。
回答by Chris Marisic
There is specifically a SortedSet<T>collection in .NET4.
This would give you sorting, but unlikely to be insertion order sorting. Since you can use a custom ICompareryou could theoretically make this do anything.
这会给你排序,但不太可能是插入顺序排序。由于您可以使用自定义IComparer,因此理论上您可以使其执行任何操作。
回答by Colonel Panic
Reading the source code for HashSet.AddIfNotPresentyou can see insertion order is preserved assuming there haven't been any deletions.
阅读HashSet.AddIfNotPresent的源代码,你可以看到插入顺序被保留,假设没有任何删除。
Thus new HashSet<string> { "Tom", "Dick", "Harry" }preserves order, but if you then remove Dick and add Rick, the order will be ["Tom", "Rick", "Harry"].
因此new HashSet<string> { "Tom", "Dick", "Harry" }保留了顺序,但是如果您随后移除 Dick 并添加 Rick,则顺序将是 ["Tom", "Rick", "Harry"]。
回答by Sudhir Jonathan
No, a hash set won't preserve insertion order, at least not predictably. You could use a LinkedHashSet (Java), or an equivalent. A LinkedHashSet will preserve order.
不,散列集不会保留插入顺序,至少无法预测。您可以使用 LinkedHashSet (Java) 或等效项。LinkedHashSet 将保留顺序。
If you want order, you shouldn't even be using a set in the first place... its not made for ordered elements, except in exceptional cases.
如果你想要顺序,你甚至不应该首先使用集合......它不是为有序元素制作的,除非在特殊情况下。
EDIT: sounds like I'm preaching :-/ Sorry.
编辑:听起来我在说教:-/对不起。

