2012-03-08 14 views
9

私はまだC#で​​新しくなっていますが、具体的なケースではListの代わりにHashSetを使用したフォーラムの掲示によって利点を気づいています。HashSetを反復する最も速く/最も安全な方法は何ですか?

私は現在、大量のデータを単一のListに保存しているわけではありませんが、頻繁にそのメンバーをチェックする必要はありません。

私は実際にそれを繰り返し処理する必要がありますが、格納されたり取得された順序は実際問題ではありません。

私は、各ループが実際には次のものよりも遅いため、可能な限り速い方法でこれをどうやって行うことができますか?

.Contains()のチェック数は、少なくともリストのパフォーマンスを傷つけているので、少なくともHashSetのパフォーマンスと比較すると便利です。

編集:私は現在、リストを使用しており、多数の場所で繰り返し処理しており、それぞれの場所で異なるコードが実行されています。ほとんどの場合、現在のリストには、2次元配列を参照するために使用するポイント座標が含まれています。次に、リストの基準に基づいて操作を実行します。

私の質問に直接答えがないのであれば問題ありませんが、HashSetを超える反復方法があると仮定して、ちょうどforeachサイクルを超えています。私は現在、他の方法が何であるか、彼らが提供する利点などについて暗闇の中にいます。他の方法があると仮定すると、典型的な好ましい方法の選択は無視されます。それはスイートではありません(私のニーズはかなり基本的です)。

私はボトルネックであるため、時期尚早に最適化する限り、私はすでにリストを使用していることを知っています。この問題を解決する方法は、私が立ち往生しているところです。正確に詰まっていませんが、繰り返しテストしてホイールを作り直したいとは思っていませんでした。私ができる最善の方法です(これは3ヶ月以上投資された大規模なプロジェクトです。リストはどこにでもありますしかし、私は重複したくない、たくさんのデータを持っている、特定の順序で格納する必要がないなど、確かにあるものがあります)。

+1

反復で何をする予定ですか?コードを実行しますか?何かを数える? –

+3

あなたは時期尚早に最適化しています。今では、データ構造とコードのパフォーマンスの関係を完全に無視する必要はありませんが、HashSetのセマンティクスが必要な場合は、プログラムのコンテキストで反復をプロファイリングし、通常はどうなるかをプロファイルします走る反復がパフォーマンスのボトルネックではない場合は、それはあなたの時間の価値はありません。それがテストされると仮定するだけではありません。 –

+1

私はその答えについて何も知らないが、私の大会では、最も速い方法が最も安全で、最も安全な方法は最速ではないと言われています。一つの方法が最も速くて安全な方法であれば、他の方法は必要ありません。私は間違っているかもしれません。 – nawfal

答えて

8

foreachループには、インデックスされたコレクション(配列など)に少量の追加オーバーヘッドがあります。 これは主にforeachがforループよりも少しだけ境界チェックを行うためです。

HashSetにはインデクサーがないため、列挙子を使用する必要があります。

この場合、foreachは、コレクション内を移動する際にMoveNext()のみを呼び出すため、効率的です。

また、Parallel.ForEachは、ループ内の作業とHashSetのサイズによって、パフォーマンスを大幅に向上させることができます。

前述のように、プロファイリングが最善の策です。

4

最初にアイテムが含まれているかどうかを判断するためにハッシュセットを反復処理するべきではありません。 HashSet(LINQではなく)メソッドを使用する必要があります。 HashSetは、指定された値がセット内にあるかどうかを調べるために各アイテムを調べる必要がないように設計されています。これは、リストを検索するための強力なツールです。

+6

彼は自分の質問で、検索と繰り返しの両方を行える必要があり、検索を繰り返す必要はないと言います。 – JamieSee

2

は厳密にヘッダに質問に答えるが、より多くのあなたの特定の問題に関する未:

私は内部的にHashSetListの両方を使用して、独自のCollection対象になるだろう。 Listを使うことができるので、反復処理は速く、Containsをチェックすることは、HashSetを使うことができるように高速です。ただそれをIEnumerableにして、foreachでこのコレクションを使用することもできます。

欠点はメモリが多いことですが、オブジェクトへの参照が2倍になり、オブジェクトの数は2倍になりません。最悪のシナリオではメモリの2倍にすぎませんが、パフォーマンスにはもっと関心があるようです。

追加、検査、および反復はこのように高速です。Listのため、削除はO(N)のままです。

編集:O(1)でも削除する必要がある場合は、ダブルポインタのリストにして、リスト内のオブジェクトの場所をすばやく見つけることができるようにHashSetを辞書にします。

0

私は同じ問題を抱えていました.HashSetは一意の要素の追加に非常に適していますが、forループで要素を取得すると非常に遅くなります。私はHashSetを配列に変換してforを実行して解決しました。

関連する問題