15

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?

1 Answer 1

31

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)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.