map () et flatMap ()
map()
Prend simplement une fonction un paramètre lambda où T est l'élément et R l'élément de retour construit à l'aide de T. À la fin, nous aurons un flux avec des objets de type R. Un exemple simple peut être:
Stream
.of(1,2,3,4,5)
.map(myInt -> "preFix_"+myInt)
.forEach(System.out::println);
Il prend simplement les éléments 1 à 5 de Type Integer
, utilise chaque élément pour construire un nouvel élément à partir de type String
avec valeur "prefix_"+integer_value
et l'imprime.
flatMap()
Il est utile de savoir que flatMap () prend une fonction F<T, R>
où
T est un type à partir duquel un Stream peut être construit à partir de / avec . Ce peut être une List (T.stream ()), un tableau (Arrays.stream (someArray)), etc. tout ce dont un Stream peut être avec / ou forme. dans l'exemple ci-dessous, chaque dev a plusieurs langues, donc dev. Les langues sont une liste et utiliseront un paramètre lambda.
R est le flux résultant qui sera construit à l'aide de T. Sachant que nous avons de nombreuses instances de T, nous aurons naturellement de nombreux flux de R. Tous ces flux de type R seront désormais combinés en un seul flux `` plat '' de type R .
Exemple
Les exemples de Bachiri Taoufiq voir sa réponse ici sont simples et faciles à comprendre. Pour plus de clarté, disons simplement que nous avons une équipe de développeurs:
dev_team = {dev_1,dev_2,dev_3}
, chaque développeur connaissant plusieurs langues:
dev_1 = {lang_a,lang_b,lang_c},
dev_2 = {lang_d},
dev_2 = {lang_e,lang_f}
Appliquer Stream.map () sur dev_team pour obtenir les langues de chaque développeur:
dev_team.map(dev -> dev.getLanguages())
vous donnera cette structure:
{
{lang_a,lang_b,lang_c},
{lang_d},
{lang_e,lang_f}
}
qui est essentiellement un List<List<Languages>> /Object[Languages[]]
. Pas très joli, ni Java8 !!
avec Stream.flatMap()
vous pouvez `` aplatir '' les choses en prenant la structure ci-dessus
et en la transformant {lang_a, lang_b, lang_c, lang_d, lang_e, lang_f}
, qui peut essentiellement être utilisée comme List<Languages>/Language[]/etc
...
donc à la fin, votre code aurait plus de sens comme ceci:
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();
ou simplement:
dev_team
.stream() /* {dev_1,dev_2,dev_3} */
.flatMap(dev -> dev.getLanguages().stream()) /* {lang_a,...,lang_d, lang_e, lang_f} */
.doWhateverWithYourNewStreamHere();
Quand utiliser map () et flatMap () :
À utiliser map()
lorsque chaque élément de type T de votre flux est censé être mappé / transformé en un seul élément de type R. Le résultat est un mappage de type (1 élément de départ -> 1 élément de fin) et un nouveau flux d'éléments de type R est retourné.
À utiliser flatMap()
lorsque chaque élément de type T de votre flux est censé être mappé / transformé en collections d'éléments de type R. Le résultat est un mappage de type (1 élément de début -> n éléments de fin) . Ces collections sont ensuite fusionnées (ou aplaties ) dans un nouveau flux d'éléments de type R. Ceci est utile par exemple pour représenter des boucles imbriquées .
Pré 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
.