Beispiel:
List<List<Object>> list = ...
List<Object> flat =
list.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
(taken from)
Erklärung:
// List of Lists: List<List<String>> listOfLists = new ArrayList<>(); listOfLists.add(Arrays.asList("Buenos Aires", "Córdoba", "La Plata")); listOfLists.add(Arrays.asList("Bern", "Chur", "Luzern")); List<String> result = listOfLists.stream().flatMap(list -> list.stream()).collect(Collectors.toList());
Signatur von flatMap(..):
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
T : Das Element mit dem der Stream parametrisiert ist, auf dem flatMap(..) aufgerufen wird.
Von flatMap verlanges Functional interface:
Function<? super T, ? extends Stream<? extends R>> :
interface Function<T, R> { R apply(T t); }
Das heisst bezüglich übergebener Funktion/Lambda-Expression:
Input von apply: Ist gleich dem Element-Parameter des Streams auf dem flatMap aufgerufen wird.
Output von apply: <? extends Stream<? extends R>>:
Ein Stream von irgendwas. –> Ich darf selbst bestimmen, was R dann wirklich ist. Dadurch, wie meine übergebene Funktion aktuell parametrisiert ist, wird R erst bestimmt.