`ConcurrentHashMap` is a Java map that supports updates from multiple threads. That makes it a candidate for parallel Clojure reductions, but thread safety alone does not make it usable with `clojure.core.reducers/fold`. A direct fold raises an `IllegalArgumentException` because the required key-value reduction protocol is missing. section 7.1.1
Extending `IKVReduce` lets the map participate in a fold, but the shown implementation reduces sequentially. To use parallel fold, extend `r/CollFold` instead: collect the map’s keys into a vector, then fold that vector while updating the concurrent map. section 7.1.1
(defn foldmap [m n combinef reducef] ; #1
(#'r/foldvec
(into [] (keys m))
n
combinef
reducef))
(extend-protocol r/CollFold ; #2
java.util.concurrent.ConcurrentHashMap
(coll-fold
[m n combinef reducef]
(foldmap m n combinef reducef)))
(def a-large-map (ConcurrentHashMap. (large-map 100000 100)))
(time ; #3
(dorun
(into {}
(r/fold
(combinef a-large-map)
reducef
a-large-map))))
"Elapsed time: 430.96208 msecs"
The `CollFold` extension delegates to a vector fold over the map’s keys; the example reports about 431 ms for its workload. section 7.1.1
The practical distinction is between a collection that tolerates concurrent updates and one that `fold` knows how to partition. Unsupported mutable Java collections, such as `HashMap`, should not be treated as safe substitutes. section 7.1.1
