迭代HashSet的最快/最安全的方法是什么?

时间:2012-03-08 21:33:02

标签: c# performance iteration hashset

我对C#还不熟悉,但在特定情况下通过论坛发帖使用HashSet代替List注意到了优势。

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

问题在于我确实需要迭代它,但它们存储或检索的顺序实际上并不重要。

我已经读过,因为每个循环实际上比下一个循环慢,所以我怎么能用尽可能快的方法来解决这个问题呢?

我正在进行的.Contains()检查的数量肯定会影响我的列表性能,因此至少与HashSet的性能相比会很方便。

编辑:我目前正在使用列表,在多个位置迭代它们,并且每个位置都执行不同的代码。大多数情况下,当前列表包含点坐标,然后我将其用于引用二维数组,然后根据列表的条件执行某些操作或其他操作。

如果我的问题没有直接答案,那很好,但我认为可能有其他方法迭代HashSet而不仅仅是foreach周期。我目前处于黑暗状态,甚至可能有其他方法,它们提供了哪些优势等等。假设还有其他方法,我还假设有一种典型的首选方法,只有在它不能满足需求(我的需求非常基本)。

就过早优化而言,我已经知道使用列表,因为我是一个瓶颈。如何解决这个问题是我陷入困境的地方。甚至没有完全卡住,但我不想通过重复测试重新发明轮子只是为了发现我已经尽力而为(这是一个投资超过3个月的大型项目,列表无处不在,但肯定有一些我不想重复,有大量数据,不需要以任何特定顺序存储,等等。)

4 个答案:

答案 0 :(得分:9)

foreach循环在索引集合(如数组)上有少量的额外开销。 这主要是因为foreach比for循环更多地进行边界检查。

HashSet没有索引器,因此您必须使用枚举器。

在这种情况下,foreach是高效的,因为它只在移动集合时调用MoveNext()。

此外,Parallel.ForEach可以显着提高您的性能,具体取决于您在循环中所做的工作以及HashSet的大小。

如前所述,分析是最好的选择。

答案 1 :(得分:3)

您不应该首先在哈希集上进行迭代,以确定项目是否在其中。您应该使用HashSet(而不是LINQ)contains方法。 HashSet的设计使得它不需要查看每个项目以查看是否有任何给定值在集合内部。这就是使它在List上搜索的强大功能。

答案 2 :(得分:1)

不严格回答标题中的问题,但更多地涉及您的具体问题:

我会在内部制作您自己的Collection对象,同时使用HashSetList。迭代很快,因为您可以使用List,检查Contains是快速的,因为您可以使用HashSet。只需将其设为IEnumerable,您也可以在foreach中使用此集合。

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

通过这种方式添加,检查和迭代很快,由于List,只有删除仍为O(N)。

编辑:如果删除也需要为O(1),请使用doubly linked list而不是常规列表,并将hashSet改为Dictionary<KeyType, Cell>。您可以检查包含字典的字典,还可以快速查找包含数据的单元格,因此从数据结构中删除速度很快。

答案 3 :(得分:0)

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