私はalotのテーブル検索を行うプログラムを書いています。そのため、Data.Map
(もちろん)だけでなくData.HashMap
とData.Hashtable
にも出会ったとき、Haskellのドキュメントをよく読んでいました。私はハッシュアルゴリズムの専門家ではありません。パッケージを調べたところ、それらはすべて本当に似ているように見えます。そのように私は思っていました:
1:主な違いは何ですか?
2:〜4000のキーと値のペアのマップ/テーブルで大量のルックアップを行う場合、どちらが最もパフォーマンスが良いでしょうか?
1:主な違いは何ですか?
Data.Map.Map
は内部的にバランスのとれたバイナリツリーであるため、ルックアップの時間の複雑さはO(log n)です。私はそれが " persistent "データ構造であると考えています。つまり、構造の関連する部分のみが更新された状態で変更操作が新しいコピーを生成するように実装されています。Data.HashMap.Map
はData.IntMap.IntMap
内部的に、パトリシアツリーとして実装されます。ルックアップの時間の複雑さはO(min(n、W))です。ここで[〜#〜] w [〜#〜]はビット数です整数で。また、「永続的」です。Data.HashTable.HashTable
は実際のハッシュテーブルで、時間の複雑さはO(1)ですが、ルックアップの場合です。ただし、変更可能なデータ構造です。操作はインプレースで行われるため、行き詰まっています。 IO
モナドで使用したい場合。2:〜4000のキーと値のペアのマップ/テーブルで大量のルックアップを行う場合、どちらが最もパフォーマンスが良いでしょうか?
残念ながら、私があなたに与えることができる最良の答えは「それは依存する」です。漸近的な複雑さを文字通りとると、O [log 4000)=約12がData.Map
、O(min(4000、64))= 64 for Data.HashMap
およびO(1) = 1 for Data.HashTable
。しかし、それは実際にはそのようには機能しません...コードのコンテキストでそれらを試す必要があります。
_Data.Map
_と_Data.HashMap
_の明らかな違いは、前者はOrd
にキーを必要とし、後者はHashable
キーを必要とすることです。共通キーのほとんどは両方なので、それは決定的な基準ではありません。私は_Data.HashTable
_についてまったく経験がないので、コメントすることはできません。
_Data.HashMap
_と_Data.Map
_のAPIは非常に似ていますが、_Data.Map
_はより多くの関数をエクスポートします。alter
などの一部は_Data.HashMap
_にありませんが、その他は厳格および非厳格のバリアント、_Data.HashMap
_(私は nordered-containers からのハッシュマップを意味していると思います)は、別々のモジュールで遅延および厳格なAPIを提供します。 APIの共通部分のみを使用している場合、切り替えは本当に簡単です。
パフォーマンスに関しては、_Data.HashMap
_ of nordered-containers の検索がかなり高速で、最後に測定しましたが、特に_Data.IntMap
_または_Data.Map
_よりも明らかに高速でした。 nordered-containers の(まだリリースされていない)HAMTブランチ。挿入については、多かれ少なかれ_Data.IntMap
_と同等であり、_Data.Map
_よりも多少高速でしたが、私は少しあいまいです。
どちらもほとんどのタスクに対して十分なパフォーマンスを発揮します。そうでないタスクについては、とにかくオーダーメイドのソリューションが必要になるでしょう。ルックアップについて具体的に尋ねることを考慮して、私は_Data.HashMap
_にエッジを与えます。
Data.HashTable
のドキュメントに、「 hashtables パッケージを使用する」と記載されています。ハッシュテーブルが優れたパッケージである理由を説明する素敵なブログ投稿があります here 。 STモナドを使用します。