2012-03-08 119 views
9

我对C#还是比较陌生,但是在特定情况下通过论坛发帖使用HashSet而不是List来发现优点。迭代HashSet的最快/最安全的方法是什么?

我目前的情况并不是我在单个List上存储了大量的数据,而是我不得不经常检查它的成员。

问题是我确实需要遍历它,但它们存储或检索的顺序实际上并不重要。

我读过每个循环实际上比下一个循环慢,所以我怎么能以最快的方法去解决这个问题呢?

我正在做的.Contains()支票的数量肯定会伤害我的表现,所以至少比较HashSet的表现会很方便。

编辑:我目前正在使用列表,在众多位置遍历它们,并在每个位置执行不同的代码。大多数情况下,当前列表包含点坐标,然后我用它来引用一个2维数组,然后根据列表的标准进行一些操作或另一个操作。

如果我的问题没有直接的答案,那很好,但我认为可能有其他方法迭代HashSet而不仅仅是foreach周期。我目前还处于黑暗中,甚至还有其他什么方法,它们提供了什么优点等等。假设还有其他方法,我还假设将会有一种典型的首选方法,只有当它不符合需求(我的需求非常基础)。

至于过早优化,我已经知道使用列表,因为我是一个瓶颈。如何去解决这个问题是我陷入困境的地方。甚至没有完全粘住,但我不想通过重复测试来重新发明轮子,只发现我已经以最好的方式做到了这一点(这是一个投入时间超过3个月的大型项目,列表无处不在,但肯定有一些我不想重复,有很多数据,不需要按任何特定顺序存储等)。

+1

你打算在迭代中做什么?执行代码?数点什么? – 2012-03-08 21:37:29

+3

您正在过早优化。现在,这并不意味着你应该完全忽略数据结构和代码的性能影响,但是如果你需要HashSet的语义,那么下一步就是在你的程序的上下文中剖析迭代,以及它通常如何跑。如果迭代不是性能瓶颈,那么继续前进,这是不值得的。不要只是假设它会,测试。 – 2012-03-08 21:37:30

+1

我对这个答案一无所知,但是我的约定说最快的方法不会是最安全和最安全的方法。我相信如果一种方法既快又安全,那么就不需要其他方法。我可能是错的。 – nawfal 2012-03-08 21:38:12

回答

8

foreach循环在索引集合(如数组)上有少量额外开销。 这主要是因为在foreach做多一点界限比for循环检查。

HashSet没有索引器,所以你必须使用枚举器。

在这种情况下的foreach是有效率的,因为它仅在其移动通过收集调用的MoveNext()。

而且Parallel.ForEach可以极大地提高你的表现,这取决于你在回路中所做的工作和你的HashSet的大小。

正如前面提到的分析是你最好的选择。

4

你不应该摆在首位来遍历一个HashSet,以确定是否一个项目是在里面。你应该使用HashSet(而不是LINQ)包含方法。 HashSet的设计使得它不需要查看每个项目以查看是否有任何给定的值在集合内。这就是为什么它在搜索列表时如此强大。

+6

他在他的问题中说,他需要能够搜索和迭代,而不是迭代搜索。 – JamieSee 2012-03-08 21:50:41

2

没有严格回答这个问题的头,但更多的关于您的具体问题:

我会提出这样既使用HashSetList内部自己Collection对象。迭代速度很快,因为您可以使用列表,检查Contains速度很快,因为您可以使用HashSet。只需将它设为IEnumerable,您也可以在foreach中使用此集合。

缺点是更多的内存,但只有对象的两倍的引用,而不是对象的两倍。最糟糕的情况是只有内存的两倍,但你似乎更关心性能。

通过这种方式添加,检查和迭代的速度很快,因为List,只有删除仍然是O(N)。

编辑:如果去除也需要O(1),使它成为一个双指针列表,并使HashSet一个字典,以便您可以快速找到列表中的对象的位置。

0

我有同样的问题,其中HashSet很适合添加独特的元素,但在for循环中获取元素时非常慢。我通过将HashSet转换为数组然后运行它来解决它。

相关问题