2012-03-08 116 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轉換爲數組然後運行它來解決它。

相關問題