map () i flatMap ()
map()
Po prostu przyjmuje funkcję param lambda, w której T jest elementem, a R element powrotu zbudowany za pomocą T. Na końcu będziemy mieli strumień z obiektami typu R. Prostym przykładem może być:
Stream
.of(1,2,3,4,5)
.map(myInt -> "preFix_"+myInt)
.forEach(System.out::println);
Po prostu bierze elementy od 1 do 5 typu Integer
, używa każdego elementu do zbudowania nowego elementu z typu String
o wartości "prefix_"+integer_value
i drukuje go.
flatMap()
Warto wiedzieć, że flatMap () przyjmuje funkcję F<T, R>
gdzie
T jest rodzajem, z którego można budować strumień z / z . Może to być lista (T.stream ()), tablica (Arrays.stream (someArray)) itp. Cokolwiek, z czego strumień może być w / lub w formie. w poniższym przykładzie każdy deweloper ma wiele języków, więc dev. Języki to lista i będzie używać parametru lambda.
R jest powstałym Strumieniem, który zostanie zbudowany przy użyciu T. Wiedząc, że mamy wiele wystąpień T, naturalnie będziemy mieli wiele Strumieni od R. Wszystkie te Strumienie Typu R zostaną teraz połączone w jeden pojedynczy „płaski” Strumień od Typu R .
Przykład
Przykłady Bachiri Taoufiq, które widzą tutaj swoją odpowiedź, są proste i łatwe do zrozumienia. Dla jasności, powiedzmy, że mamy zespół programistów:
dev_team = {dev_1,dev_2,dev_3}
, przy czym każdy programista zna wiele języków:
dev_1 = {lang_a,lang_b,lang_c},
dev_2 = {lang_d},
dev_2 = {lang_e,lang_f}
Zastosowanie Stream.map () na dev_team, aby uzyskać języki każdego dewelopera:
dev_team.map(dev -> dev.getLanguages())
da ci tę strukturę:
{
{lang_a,lang_b,lang_c},
{lang_d},
{lang_e,lang_f}
}
co jest w zasadzie a List<List<Languages>> /Object[Languages[]]
. Nie tak bardzo ładnie, ani Java8 !!
dzięki Stream.flatMap()
czemu możesz „spłaszczyć” rzeczy, ponieważ bierze powyższą strukturę
i przekształca ją {lang_a, lang_b, lang_c, lang_d, lang_e, lang_f}
, co można zasadniczo wykorzystać jako List<Languages>/Language[]/etc
...
więc w końcu twój kod miałby więcej sensu:
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();
lub po prostu:
dev_team
.stream() /* {dev_1,dev_2,dev_3} */
.flatMap(dev -> dev.getLanguages().stream()) /* {lang_a,...,lang_d, lang_e, lang_f} */
.doWhateverWithYourNewStreamHere();
Kiedy używać map () i flatMap () :
Użyj, map()
gdy każdy element typu T ze strumienia ma być odwzorowany / przekształcony w pojedynczy element typu R. Wynikiem jest mapowanie typu (1 element początkowy -> 1 element końcowy) i nowy strumień elementów typu R jest zwracany.
Użyj, flatMap()
gdy każdy element typu T ze strumienia ma zostać zmapowany / przekształcony w kolekcję elementów typu R. Wynikiem jest mapowanie typu (1 element początkowy -> n elementów końcowych) . Kolekcje te są następnie łączone (lub spłaszczane ) z nowym strumieniem elementów typu R. Jest to przydatne na przykład do reprezentowania zagnieżdżonych pętli .
Przed 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
.