clojure的APersistentMap实现有什么区别

时间:2013-05-13 06:41:04

标签: clojure

我试图找出PersistentHashMap,PersistentArrayMap,PersistentTreeMap和PersistentStructMap之间的区别。

此外,如果我使用{:a 1},它会给我一个PersistentArrayMap,但是如果我给它以外的对象或其他东西,它可以改为其他任何一个吗?

2 个答案:

答案 0 :(得分:16)

您列出的四个实施分为三组:

  1. “literal”PersistentArrayMapPersistentHashMap:处理地图文字时使用的基本地图类型(虽然构造函数也可以在处理时使用不同的行为重复键 - 在Clojure 1.5.x文字中,当它们发现重复键时抛出异常,构造函数的工作方式类似于从左到右重复conj;这种行为已经从版本发展到版本)。当超过一定数量的条目(9 IIRC)时,阵列映射会被提升为哈希映射。存在阵列映射是因为它们对于小地图来说更快;它们也与散列映射的不同之处在于它们在升级到散列映射之前以插入顺序保留条目(您可以使用clojure.core/array-map来获取任意大的数组映射,如果您确实知道自己会从插入中获益,这可能很有用-order遍历和映射不会太大,可能只是略高于通常的阈值; NB。后续assoc这样的超大数组映射将返回哈希映射)。数组映射使用具有键和值交错的数组; PHM使用持久版本的Phil Bagwell的哈希数组映射trie,单独链接用于哈希冲突和单独的节点类型,用于大多数空的和至少半满的节点,并且很容易是Clojure中最复杂的数据结构。

  2. 已排序PersistentTreeMap个实例仅由特殊请求创建(对sorted-mapsorted-map-by的调用)。它们被实现为红黑树并按特定顺序维护条目,如使用compare创建的默认sorted-map比较器或使用sorted-map-by创建的用户提供的比较器所指定的。

  3. 特殊目的,可能已弃用PersistentStructMap并非经常使用,并且大部分都被视为已弃用以支持记录,尽管我实际上现在还不记得有一个官方的弃用通知。最初的目的是提供对特定快速访问某些常用密钥的映射。现在可以使用关键字进行字段访问时使用记录来完成此操作(关键字位于运算符位置:(:foo instance-of-some-record-with-field-foo)),但重要的是要注意记录不是=到具有相同条目的常规映射

  4. 所有这四种内置映射类型都属于相同的“相等分区”,也就是说,如果(并且仅当)它们包含相同的键(如上所述),则上述四个类之一的任何两个映射都是相同的(如由Clojure的=确定,具有相同的相应值。如上面的3.中所述,记录是类似地图的,但每种记录类型形成它自己的相等分区。

答案 1 :(得分:4)

它们是持久性地图的不同实现(它们都扩展为APersistentMap)。因此PersistentArrayMap使用数组作为底层数据结构来实现持久映射,类似地,其他实现使用不同的底层数据结构。

不同实现的原因是它们在不同情况下提供不同的好处(因为实现的效率取决于底层数据结构)。

从开发人员的角度来看,它被抽象出来,因此你不应该直接使用它 它们使用APersistentMap抽象类或IPersistentMap接口(如果某些特定情况需要某些类型检查等)。

根据地图中元素的数量,使用各种实现。

(type (into {} (map #(-> [% %]) (range 5))))
=> PersistentArrayMap
(type (into {} (map #(-> [% %]) (range 10))))
=> PersistentHashMap