PersistentHashMap、PersistentArrayMap、PersistentTreeMap、および PersistentStructMap の違いを理解しようとしています。
また、それを使用する{:a 1}
と PersistentArrayMap が得られますが、オブジェクトまたはキー以外のものを与えると、これを他のものに変更できますか?
PersistentHashMap、PersistentArrayMap、PersistentTreeMap、および PersistentStructMap の違いを理解しようとしています。
また、それを使用する{:a 1}
と PersistentArrayMap が得られますが、オブジェクトまたはキー以外のものを与えると、これを他のものに変更できますか?
リストした 4 つの実装は、次の 3 つのグループに分類されます。
"literal" :PersistentArrayMap
およびPersistentHashMap
: マップ リテラルを処理するときに使用される基本的なマップ タイプ (コンストラクター関数も、重複キーの処理に関して異なる動作で使用できますが、Clojure 1.5.x では、リテラルは重複キーを検出すると例外をスローしますが、コンストラクター関数は左のように機能します-to-right の繰り返しconj
ing; この動作はバージョンごとに進化しています)。配列マップは、特定の数のエントリ (9 IIRC) を超えると、ハッシュ マップに昇格します。配列マップが存在するのは、小さいマップの方が高速であるためです。また、ハッシュ マップに昇格する前にエントリを挿入順に保持するという点でも、ハッシュ マップとは異なります (次を使用できます)。clojure.core/array-map
任意に大きな配列マップを取得します。これは、挿入順序トラバーサルの恩恵を受けることが本当にわかっていて、マップが大きすぎず、おそらく通常のしきい値を少し超えない場合に役立ちます。注意。このような大きすぎる配列マップに続くassoc
は、ハッシュ マップを返します)。配列マップは、キーと値がインターリーブされた配列を使用します。PHM は、Phil Bagwell のハッシュ配列マップ トライの永続的なバージョンを使用し、ハッシュの衝突に別のチェーンを使用し、ほぼ空で少なくとも半分がいっぱいのノードに別のノード タイプを使用します。これは、Clojure で最も複雑なデータ構造です。
sorted :PersistentTreeMap
インスタンスは、特別なリクエスト (sorted-map
またはの呼び出しsorted-map-by
) によってのみ作成されます。これらは赤黒ツリーとして実装され、特定の順序でエントリを維持します。これは、 で作成されたcompare
場合はデフォルトのコンパレータ、 で作成されたsorted-map
場合はユーザー指定のコンパレータで指定されますsorted-map-by
。
special-purpose, おそらく deprecated :PersistentStructMap
あまり頻繁には使用されず、ほとんどの場合、レコードを支持して非推奨と見なされていますが、公式の非推奨通知があったかどうかは今のところ思い出せません. 当初の目的は、頻繁に使用される特定のキーに特に高速にアクセスできるマップを提供することでした。これは、フィールド アクセスにキーワードを使用する場合 (演算子の位置: にキーワードを使用) にレコードを使用して実行できるようになりまし(:foo instance-of-some-record-with-field-foo)
た=
。
これら 4 つの組み込みマップ タイプはすべて、同じ「等価パーティション」に分類されます。つまり、上記の 4 つのクラスのいずれかの 2 つのマップは、それらが同じキーを含む場合 (およびその場合にのみ) 等しくなります (Clojure の=
) 対応する値は同じです。上記の 3. で述べたように、レコードはマップに似ていますが、各レコード タイプは独自の等価パーティションを形成します。
それらは永続マップの異なる実装です (それらはすべて拡張されますAPersistentMap
)。したがって、 PersistentArrayMap
配列を基になるデータ構造として使用して永続的なマップを実装し、同様に他の実装では異なる基になるデータ構造を使用します。
異なる実装の理由は、異なる状況で異なる利点を提供するためです (実装の効率は基礎となるデータ構造に依存するため)。
開発者の観点からは、抽象化されているため、それらを直接使用するのではなく、代わりにAPersistentMap
抽象クラスまたはIPersistentMap
インターフェイスを操作する必要があります (特定のケースで型チェックなどが必要な場合)。
マップ内の要素の数に応じて、さまざまな実装が使用されます。
(type (into {} (map #(-> [% %]) (range 5))))
=> PersistentArrayMap
(type (into {} (map #(-> [% %]) (range 10))))
=> PersistentHashMap