map () und flatMap ()
map()
Nimmt einfach eine Funktion einen Lambda-Parameter, wobei T das Element und R das mit T erstellte Rückgabeelement ist. Am Ende haben wir einen Stream mit Objekten vom Typ R. Ein einfaches Beispiel kann sein:
Stream
.of(1,2,3,4,5)
.map(myInt -> "preFix_"+myInt)
.forEach(System.out::println);
Es werden einfach die Elemente 1 bis 5 des Typs verwendet Integer
, mit jedem Element ein neues Element aus dem Typ String
mit Wert erstellt "prefix_"+integer_value
und ausgedruckt.
flatMap()
Es ist nützlich zu wissen, dass flatMap () eine Funktion übernimmt, F<T, R>
bei der
T ist ein Typ, aus dem ein Stream erstellt werden kann . Es kann eine Liste (T.stream ()), ein Array (Arrays.stream (someArray)) usw. sein, alles, was ein Stream mit / oder Form sein kann. Im folgenden Beispiel hat jeder Entwickler viele Sprachen, also Entwickler. Languages ist eine Liste und verwendet einen Lambda-Parameter.
R ist der resultierende Stream, der mit T erstellt wird. Da wir wissen, dass wir viele Instanzen von T haben, werden wir natürlich viele Streams von R haben. Alle diese Streams von Typ R werden jetzt zu einem einzigen "flachen" Stream von Typ R kombiniert .
Beispiel
Die Beispiele von Bachiri Taoufiq , deren Antwort hier zu sehen ist, sind einfach und leicht zu verstehen. Nehmen wir zur Klarheit an, wir haben ein Entwicklerteam:
dev_team = {dev_1,dev_2,dev_3}
, wobei jeder Entwickler viele Sprachen beherrscht:
dev_1 = {lang_a,lang_b,lang_c},
dev_2 = {lang_d},
dev_2 = {lang_e,lang_f}
Anwenden von Stream.map () auf dev_team, um die Sprachen der einzelnen Entwickler abzurufen:
dev_team.map(dev -> dev.getLanguages())
gibt Ihnen diese Struktur:
{
{lang_a,lang_b,lang_c},
{lang_d},
{lang_e,lang_f}
}
Das ist im Grunde ein List<List<Languages>> /Object[Languages[]]
. Nicht so sehr hübsch, noch Java8-ähnlich !!
mit können Stream.flatMap()
Sie Dinge "abflachen", während es die obige Struktur nimmt
und sie in verwandelt {lang_a, lang_b, lang_c, lang_d, lang_e, lang_f}
, was im Grunde genommen als List<Languages>/Language[]/etc
...
Am Ende wäre Ihr Code also sinnvoller:
dev_team
.stream() /* {dev_1,dev_2,dev_3} */
.map(dev -> dev.getLanguages()) /* {{lang_a,...,lang_c},{lang_d}{lang_e,lang_f}}} */
.flatMap(languages -> languages.stream()) /* {lang_a,...,lang_d, lang_e, lang_f} */
.doWhateverWithYourNewStreamHere();
oder einfach:
dev_team
.stream() /* {dev_1,dev_2,dev_3} */
.flatMap(dev -> dev.getLanguages().stream()) /* {lang_a,...,lang_d, lang_e, lang_f} */
.doWhateverWithYourNewStreamHere();
Wann man map () und flatMap () benutzt :
Verwenden Sie diese Option, map()
wenn jedes Element vom Typ T aus Ihrem Stream einem einzelnen Element vom Typ R zugeordnet / transformiert werden soll . Das Ergebnis ist eine Zuordnung des Typs (1 Startelement -> 1 Endelement) und eines neuen Streams von Elementen des Typs R. ist zurück gekommen.
Verwenden Sie diese Option, flatMap()
wenn jedes Element vom Typ T aus Ihrem Stream einer Sammlung von Elementen vom Typ R zugeordnet / transformiert werden soll . Das Ergebnis ist eine Zuordnung vom Typ (1 Startelement -> n Endelemente) . Diese Sammlungen werden dann zu einem neuen Strom von Elementen vom Typ R zusammengeführt (oder abgeflacht ). Dies ist beispielsweise nützlich, um verschachtelte Schleifen darzustellen .
Vor Java 8:
List<Foo> myFoos = new ArrayList<Foo>();
for(Foo foo: myFoos){
for(Bar bar: foo.getMyBars()){
System.out.println(bar.getMyName());
}
}
Post Java 8
myFoos
.stream()
.flatMap(foo -> foo.getMyBars().stream())
.forEach(bar -> System.out.println(bar.getMyName()));
map :: Stream T -> (T -> R) -> Stream R
,flatMap :: Stream T -> (T -> Stream R) -> Stream R
.