2011-10-23 8 views
4

私は単純な要件を持っています。私は数百万の文字列を持っており、小さなセットに存在するかどうかをテストしたいと思っています。私はList<T>HashSet<T>をこのセットに使用するかどうか疑問に思っています。どのようにHashSetが<T>です。リストよりも速く収まる<T>.Contains?

たとえば、100個の文字列があり、数百万の文字列が存在するかどうかを確認する必要がある場合は、HashSet<T>が最適です。

しかし、私の場合は

は、.NETはとても速くなる可能性が List<T>Containsを呼び出し、 HashSet<T>Containsを呼び出すときにハッシュの何百万人( GetHashCodeへの呼び出し)を計算するために持っているようですか?

この前提が正しいかどうか誰にも説明できますか?

答えて

10

どちらも適切ではないようです - HashSet<string>のように聞こえますが、それは私にとって最善の方法かもしれません。

はい、.NETは各文字列のハッシュコードを計算する必要があります。問題は、候補セット内の何百もの文字列のそれぞれと等しいかどうかをチェックするかどうかです。

すべてのパフォーマンスに関する質問ごとに、推測よりも実際にテストする必要があります。たとえば、すべての文字列の長さが異なり、すべてが長ければ、Equalsはそれぞれの候補に対して安くなり、GetHashCodeには時間がかかることがあります。しかし、あなたのすべての文字列が同じ6文字から始まる長さ10の場合、GetHashCodeはかなり安いでしょうが、各文字列の等価性チェックはこれらの共通接頭文字すべてをチェックする必要があります。どちらがあなたの実際の状況にもっと似ていますか?あなたのベンチマークは何を示していますか?あなたはどれくらい速いですかこれが必要ですか?

+0

非常に良い答え!私はHybridDictionaryクラスを見つけました。ここでは値をnullとして保存して、それをHashSetと同じように本質的にしています。 – Muis

+0

@ Joshua:具体的なパフォーマンスデータなしで、非genericのHybridDictionaryクラス(要素を含むだけでなく値にキーをマッピングするクラス)を使用しません。 'List 'と 'HashSet 'の両方が遅すぎますか? 'HybridDictionary'は、実際のデータと、EqualsとGetHashCodeの呼び出しがどれほど高価であるかに依存して、スイッチオーバーポイントが意味を成す場所が分からないことに注意してください。 –

+0

私は現在、HashSet を使用していますが、時には3つの値が含まれていることもあり、時には何千もの値が含まれているため、例えばHybridHashsetのようなものを探しています。私は正確に '100'を決して計算することはできないことを知っていますが、おそらくそれで十分でしょう。 – Muis

2

私はディクショナリはキーのハッシュをキャッシュし、明らかにあなたが検索している文字列のハッシュを一度しか計算しないと思います。あなたの文字列のセットが静的でまれにしか変更されていない場合は、不変のリストをソートしてArray.BinarySearchを使用するほうが速いかもしれませんが、コードをあまりにも複雑にするので私はそれがはるかに高速だったことを確認したベンチマークで)。

+0

私はあなたがその質問を誤解していると思います。問題は何百万もの文字列を検索しているため、何もキャッシュできないということです。 – Muis

+0

だからあなたの問題は:文字列をハッシュし、100の他の文字列でそれを100回比較してハッシュや検索で直接検索する方が速いのですか?あなたはベンチマークしなければなりません。私はブレークポイントが固定されているとは思わない。 – xanatos

+0

私は解決策を見つけたと思う:HybridDictionaryクラス、それは自動的にブレークポイントで切り替える。 – Muis

関連する問題