2016-02-23 13 views
9

Java 8 ha portato l'interfaccia Stream e con essa conveniente mappa/filtro/riduce le operazioni sulle raccolte Java (e altre cose che possono essere trasformate in un flusso).Consumo di stream Java in Clojure

Trovo gli streams scomodi e prolissi da utilizzare da Clojure quando interagiscono con le API Java che li producono.

Confronta - Java:

Pattern.compile("\\s+").splitAsStream("one two three") 
     .filter(s -> !s.contains("o")) 
     .map(String::toUpperCase) 
     .findFirst() 
     .orElse(null); // => "THREE" 

Clojure, cercando di utilizzare la stessa 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" 

C'è un approccio migliore per consumare le API Java stream-based in Clojure? È possibile trasformare uno stream in un seq e utilizzare le stesse funzioni di trasformazione di Clojure, come remove, partition, take?

risposta

20

È possibile ottenere un java.util.Iterator dallo Stream utilizzando il suo metodo iteratore(). Si può fare una sequenza di clojure usando iteratore-seq:

(-> stream 
    .iterator 
    iterator-seq)