web-dev-qa-db-ja.com

どちらが速いですか? List.contains()またはMap.containsKey()

値のペアを探すアルゴリズムを書いています。これを加算すると、探している別の値が得られます。

Mapを使用すると、アルゴリズムがO(n²)から高速化されることがわかりました。私は後でMapに含まれる値を実際には使用しないので、Listで十分であることに気付きました。

私はGoogleでパワー検索を行いましたが、質問のタイトルにこれらのメソッドの漸近実行時間に関する情報は見つかりませんでした。

そのような情報をどこで探すべきか指摘できますか?

24
Adam Arold

list.containsはO(n)であるのに対し、map.containsKey is O(1) for hashmaps、O(logn) for treemaps。forハッシュマップ、google for hashtable。google for treemap、google for binary treeまたはウィキペディアには、これらの主題に関する優れたエントリがあります。

マップが必要ない場合は、対応するセットを使用できます。内部では、対応するマップに関して実装されており、値は単なるダミーのシングルトンオブジェクトです。

ただし、クラスHashtableを回避するように注意してください。それは現代図書館の考古学的な遺物です。あなたの場合、HashSetがおそらく最良の選択です。

49
Marko Topolnik

MapListはインターフェイスであるため、それらの実装やパフォーマンスに関する情報はありません。ただし、最新の実装(LinkedListの場合はArrayListまたはListHashMapの場合はMap)を使用する場合、contains()メソッドは、最悪の場合、リスト全体を調べ、要素を各エントリと比較する必要があります。 O(n)操作です。

HashMapを使用する場合、実装は根本的に異なります。HashMapには、要素よりも多くのエントリを持つ配列が含まれます(実際には、4n/3から3nの配列サイズがあります。/2マップのn要素)。これは、intであるキーのハッシュを計算し、それを0と配列サイズの間でラップします(この数がiであるとしましょう)。次に、配列のインデックスiに要素を配置します(以前のインデックスが既に取得されている場合はi+1i+2…)。したがって、containsKeyを使用してキーの存在を確認すると、ハッシュとiの値が再計算され、ii+1…が確認されます。空の配列セルが見つかるまでインデックスを作成します。理論的には、O(n)最悪の場合、配列がほぼ満杯の場合、すべてのキーがiの値とほぼ同じですが、ハッシュは良好です。関数には、一定時間のcontains関数とget関数があります(ただし、配列のサイズを変更する必要がない場合、要素の追加は高速です[〜#〜 ] really [〜#〜]遅い-各キーのインデックスを再計算する必要があると思います)。

したがって、コレクション内の主要な外観を確認する必要があり、順序を維持する必要がない場合、マップは本当に高速になります(そのためのSortedHashMapはありますが、パフォーマンスはわかりません)。より多くのメモリが必要になります。

また、Key-Valueが必要ない場合は、HashSet(内部的にはHashMapと同じ)を使用できます。

6
Ilod

HashMapでの検索はO(1)で行われるため、HashMapを使用していることを考慮したMap.containsKey()。

List.contains()は通常、シーケンシャル検索またはバイナリ検索を使用する必要があるため、複雑度は少なくともO(log n)になります。

0
Varun