【问题标题】:What is the difference between the hash-map and array-map in clojure?clojure 中的 hash-map 和 array-map 有什么区别?
【发布时间】:2014-11-20 22:22:42
【问题描述】:

Clojure 有一个数组映射和哈希映射,我无法弄清楚两者之间的区别。如果可能的话,谁能举例说明何时使用它们中的任何一个?

【问题讨论】:

    标签: clojure hashmap array-map


    【解决方案1】:

    array-maps 保留插入顺序,但您不应该依赖这种行为,除非您知道地图不会被修改的非常简单的情况。如果您确实需要这种行为,请使用 an ordered collection

    数组映射应该用于非常小的映射(16 keys right now),因为查找和“修改”性能优于相同大小的哈希映射:

    (def arraymap (array-map :f 1 :g 2 :h 4 :y 5 :w 4))     
    (def hashmap (hash-map :f 1 :g 2 :h 4 :y 5 :w 4))
    
    (defn add-2-keys [m]
      (assoc m :new 2 :w 4))
    
    (defn access-all-keys [m]
      (mapv m [:f :g :h :y :w :not-there]))
    
    (use 'criterium.core)
    
    ; Modification 
    (bench (add-2-keys array map))
    Execution time mean : 125.640082 ns    
    (bench (add-2-keys hashmap))
    Execution time mean : 150.918197 ns
    
    ; Access
    (bench (access-all-keys arraymap))
    Execution time mean : 260.547035 ns
    (bench (access-all-keys hashmap))
    Execution time mean : 305.350156 ns
    

    【讨论】:

    • 实际上是 8 个键。内部数组是 16,但它同时包含键和值。我认为还值得指出的是,有序行为基本上是其实现的副作用,并且它的存在被解释为具有小集合的哈希映射的优化替代方案。它不是一个有序的地图实现,尽管它在较小的集合中表现得如此。同样,将其用作较小或较大集合的映射也没有错,因为当关联过去 8 个键时,它会恢复为哈希映射。
    【解决方案2】:

    数组映射和哈希映射具有相同的接口,但数组映射具有O(N) 查找复杂度(即它实现为简单的条目数组),而哈希映射具有O(1) 查找复杂度。

    数组映射具有维护插入顺序的优势(大多数情况下您不需要),因此当您执行任何迭代映射的操作(例如,mapreduce)时,您可以按照插入时的顺序处理条目。

    请注意,如果您反复“修改”(在持久化集合的意义上)一个数组映射,在某些时候它会变成一个哈希映射。例如

    user=> (type (apply assoc (array-map) (zipmap (range 10) (range 10))))
    clojure.lang.PersistentArrayMap
    user=> (type (apply assoc (array-map) (zipmap (range 100) (range 100))))
    clojure.lang.PersistentHashMap
    

    基本上,如果您不关心键顺序,则总是更喜欢哈希映射。此外,如果您确实使用数组映射,请记住查找性能权衡。

    【讨论】:

      猜你喜欢
      • 2023-03-04
      • 2019-05-14
      • 1970-01-01
      • 2016-12-24
      • 2010-10-27
      • 2018-03-08
      • 1970-01-01
      • 1970-01-01
      • 2010-10-05
      相关资源
      最近更新 更多