我试图弄清楚PersistentHashMap,PersistentArrayMap,PersistentTreeMap和PersistentStructMap之间的区别.
另外,如果我使用{:a 1}
它给我一个PersistentArrayMap但是如果我给它除了键以外的对象或东西,它可以改为任何其他的吗?
Mic*_*zyk 17
您列出的四个实现分为三组:
"literal":PersistentArrayMap
和PersistentHashMap
:处理地图文字时使用的基本地图类型(虽然构造函数也可用于处理重复键的不同行为 - 在Clojure 1.5.x文字中,当它们发现重复键时抛出异常,构造函数就像左边一样工作从右到右重复conj
;这种行为已经从版本发展到版本).当超过一定数量的条目(9 IIRC)时,阵列映射会被提升为哈希映射.存在阵列映射是因为它们对于小地图来说更快; 它们也与散列映射的不同之处在于它们在升级到散列映射之前以插入顺序保留条目(您可以使用它clojure.core/array-map
来获取任意大的数组映射,如果您确实知道您将受益于插入顺序遍历和map不会太大,也许只是略高于通常的阈值; NB.后面assoc
这样一个超大的数组映射将返回一个哈希映射).数组映射使用具有键和值交错的数组; PHM使用持久版本的Phil Bagwell的哈希数组映射trie,单独链接用于哈希冲突,单独的节点类型用于大多数空的和至少半满的节点,并且很容易成为Clojure中最复杂的数据结构.
sorted:PersistentTreeMap
实例仅由特殊请求创建(对sorted-map
or 的调用sorted-map-by
).它们被实现为红黑树并按特定顺序维护条目,如默认compare
比较器所指定的,如果使用sorted-map
或由用户提供的比较器创建的话sorted-map-by
.
特殊目的,可能已经弃用:PersistentStructMap
经常不被使用,并且大多数被视为弃用以支持记录,尽管如果有官方弃用通知我实际上现在还记不起来.最初的目的是提供对特定快速访问某些常用密钥的映射.现在,使用关键字进行字段访问时可以使用记录完成此操作(关键字位于运算符位置:) (:foo instance-of-some-record-with-field-foo)
,但重要的是要注意记录不是=
具有相同条目的常规映射.
所有这四种内置映射类型都属于相同的"相等分区",也就是说,如果(并且只有)它们包含相同的键(由Clojure确定),上面提到的四个类之一的任何两个映射都是相等的.=
)具有相同的相应值.如上面的3.中所述,记录是类似映射的,但是每个记录类型形成它自己的相等分区.
它们是持久映射的不同实现(它们都扩展了APersistentMap
)。因此,a PersistentArrayMap
使用数组作为基础数据结构来实现持久性映射,类似地,其他实现也使用不同的基础数据结构。
实施不同的原因是,它们在不同的情况下提供不同的收益(因为实施的效率取决于基础数据结构)。
从开发人员的角度来看,它是抽象的,因此您不应直接使用它们,而应使用APersistentMap
抽象的类或IPersistentMap
接口(以防在某些特定情况下需要进行类型检查等)。
根据映射中元素的数量,可以使用各种实现。
(type (into {} (map #(-> [% %]) (range 5))))
=> PersistentArrayMap
(type (into {} (map #(-> [% %]) (range 10))))
=> PersistentHashMap
Run Code Online (Sandbox Code Playgroud)