Java 8 brought the Stream
interface, and with it convenient map/filter/reduce operations on Java collections (and other things that can be turned into a stream).
I find streams awkward and verbose to use from Clojure when interoperating with Java APIs that produce them.
Compare – Java:
Pattern.compile("\\s+").splitAsStream("one two three")
.filter(s -> !s.contains("o"))
.map(String::toUpperCase)
.findFirst()
.orElse(null); // => "THREE"
Clojure, trying to use the same API:
(.. (.splitAsStream #"\s+" "one two three")
(filter
(reify java.util.function.Predicate
(test [this value] (not (.contains value "o")))))
(map
(reify java.util.function.Function
(apply [this value] (.toUpperCase value))))
(findFirst)
(orElse nil)) ; => "THREE"
Is there a better approach to consuming stream-based Java APIs in Clojure? Is it possible to turn a stream into a seq and use Clojure’s own transformation functions, like remove
, partition
, take
?
You can get a java.util.Iterator from the Stream using its iterator() method. That can be made a clojure sequence using iterator-seq:
(-> stream
.iterator
iterator-seq)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With