2015-11-03 10 views
5

In Java8 habe ich einen Stream und ich möchte eine Strom von Mappern anwenden.Wenden Sie einen Stream von Mappern auf einen anderen Stream in Java8

Zum Beispiel:

Stream<String> strings = Stream.of("hello", "world"); 
Stream<Function<String, String>> mappers = Stream.of(t -> t+"?", t -> t+"!", t -> t+"?"); 

Ich mag schreiben:

strings.map(mappers); // not working 

Aber mein aktueller bester Weg, um meine Aufgabe zu lösen, ist:

for (Function<String, String> mapper : mappers.collect(Collectors.toList())) 
    strings = strings.map(mapper); 

strings.forEach(System.out::println); 

Wie kann ich dieses Problem lösen

  • ohne die Mapper in eine Liste zu sammeln
  • ohne Verwendung eines for Schleife
  • ohne meine fließend Code zu brechen

Antwort

8

Da map erfordert eine Funktion, die auf jedes Element angewendet werden kann, aber Ihre Stream<Function<…>> kann nur sein, Einmal ausgewertet, ist es unvermeidlich, den Stream zu etwas wiederverwendbarem zu verarbeiten. Wenn es nicht ein Collection sein sollte, reduzieren nur auf einen einzigen Function:

strings.map(mappers.reduce(Function::andThen).orElse(Function.identity())) 

Komplettes Beispiel:

Stream<Function<String, String>> mappers = Stream.of(t -> t+"?", t -> t+"!", t -> t+"?"); 
Stream.of("hello", "world") 
     .map(mappers.reduce(Function::andThen).orElse(Function.identity())) 
     .forEach(System.out::println); 
+1

Andere Varianten, die funktionieren: 'mappers.reduce (Function.identity() Funktion :: andThen) ',' mappers.reduce (Function.identity(), Function :: compose) '. – rgettman

+3

@gerttman: Die 'orElse'-Variante ist eine kleine Optimierung, da sie keine Identitätsfunktion mit einer anderen Funktion kombiniert. – Holger

+0

Es wäre schön, wenn 'Function.identity()' 'compose' und' andThen' ... überschreiben würde ... Oder vielleicht würde der JIT-Compiler diese Komplexität sowieso loswerden? –

Verwandte Themen