在Clojure中,Java的computeIfAbsent或putIfAbsent相当于什么?

时间:2016-06-14 08:56:34

标签: java dictionary clojure

使用Java中的地图,您可以编写map.computeIfAbsent(key, f)来检查地图中是否存在密钥,如果没有,则在密钥上调用f以生成值,并在地图中输入该值。您还有map.putIfAbsent(key, value),如果地图中尚不存在该键,则只会将该值放入地图中。

忽略Java方法也返回值的事实,而是想要返回新映射,Clojure中的等效代码是什么?

到目前为止,我提出的最好的方法就是用

之类的东西来推销自己
(defn compute-if-absent [map key f]
  (if (key map)
    map
    (assoc map key (f key))))

有替代方法可以自己滚动吗?

3 个答案:

答案 0 :(得分:5)

Clojure映射是不可变的,因此您将始终返回具有更新内容的新映射 - 因此您的函数将始终是线程安全的。这也意味着您不能拥有一个全局变量来保存您的地图并将其变异。

compute-if-absent的实施几乎是正确的。对于虚假的密钥,它将失败,例如{false 1}。您需要更改if条件并使用contains?代替key

(defn compute-if-absent [m k f]
  (if (contains? m k)
    m
    (assoc m key (f k))))

如果确实需要与ConcurrentMap具有相同的行为,则可以在Clojure中使用Java互操作来使用它们。

答案 1 :(得分:2)

更简单的解决方案是merge使用put-if-absent

(merge {key val} m)

虽然compute-if-absent的最终结果是相同的,但无论(f key)的内容如何,​​以下代码当然会计算m

(merge {key (f key)} m)

答案 2 :(得分:0)

如果您尝试实施某种形式的缓存,那么您可以使用clojure的memoize功能。

示例:(def fast-inc (memoize inc))

请参阅:http://clojuredocs.org/clojure.core/memoize