Quelle est la différence entre la carte et flatMap méthodes en Java 8?
Dans Java 8, quelle est la différence entre Stream.map
et Stream.flatMap
méthodes?
- La signature d'un type un peu raconte toute l'histoire.
map :: Stream T -> (T -> R) -> Stream R
,flatMap :: Stream T -> (T -> Stream R) -> Stream R
. - fwiw, ces signatures ne regarde même pas comme Java. (Je sais, je sais-mais-à-dire qu'il raconte "l'histoire" wrt carte/flatMap suppose beaucoup de connaissances au sujet de la nouvelle & l'amélioration de la "Java++")
- Ce type de signature ressemble à Haskell, pas de Java. Mais il n'est pas clair si la Java signature est plus lisible:
<R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper)
. - Ha, ouais, je faisais allusion à la "effective Java". Comme C++, moderne, Java est presque méconnaissable à quelqu'un qui a commencé à l'utiliser dans les années 90 (comme je l'ai fait, dans les deux langues). Juste en réponse à cette observation, que les signatures de méthode à peine dire "toute une histoire", au moins pas plus, pas sans complément d'exposition (ou en ce que les commentateurs cas, la traduction).
- Qui est-à-dire, un
map
's mappeur lambda retourneR
, unflatMap
's mappeur lambda renvoie uneStream
deR
(Stream<R>
). Le flux renvoyé par laflatMap
s'mapper sont effectivement concaténées. Sinon, les deuxmap
etflatMap
retourStream<R>
; la différence est que le mappeur lambdas retour,R
vsStream<R>
. - Utilisation
map
si chaque élément est transformé en une valeur unique. UtilisationflatMap
si chaque élément sera transformé à plusieurs valeurs et le flux résultant doit être aplatie.
Vous devez vous connecter pour publier un commentaire.
Les deux
map
etflatMap
peut être appliquée à unStream<T>
et ils reviennent tous les deux unStream<R>
. La différence est que lemap
opération produit une valeur de sortie pour chaque valeur d'entrée, alors que laflatMap
opération produit un nombre arbitraire (zéro ou plus) des valeurs pour chaque valeur d'entrée.Cela se reflète dans les arguments de chaque opération.
La
map
opération prendFunction
, qui est appelée pour chaque valeur dans le flux d'entrée et produit une valeur de résultat, qui est envoyé vers le flux de sortie.La
flatMap
opération prend une fonction que sur le plan conceptuel veut consommer une valeur et produire un nombre arbitraire de valeurs. Toutefois, en Java, c'est gênant pour une méthode de retour d'un nombre arbitraire de valeurs, puisque les méthodes peuvent renvoyer uniquement zéro ou une valeur. On pourrait imaginer une API où le mappeur de fonction pourflatMap
prend une valeur et retourne un tableau ou unList
de valeurs, qui sont ensuite envoyés à la sortie. Étant donné que c'est le flux de la bibliothèque, particulièrement apt moyen de représenter un nombre arbitraire de valeurs de retour est pour le mapper la fonction elle-même de retour d'un ruisseau! Les valeurs du flux renvoyé par le mappeur sont drainés à partir du flux et sont transmis vers le flux de sortie. Les "touffes" de valeurs retournées par chaque appel à la mappeur de fonction ne sont pas distingués dans le flux de sortie, donc la sortie est dit avoir été aplatis.Utilisation typique est pour le mapper la fonction de
flatMap
de retourStream.empty()
si elle veut envoyer des valeurs nulles, ou quelque chose commeStream.of(a, b, c)
si elle veut retourner plusieurs valeurs. Mais bien sûr, tous les flux peuvent être retournés.flatMap
opération est l'exact opposé de l'appartement. Encore une fois, laisser les Scientifiques de l'Informatique à son tour un terme sur le dessus de la tête. Comme une fonction de l'être "transparent", ce qui signifie que vous ne pouvez pas voir quoi que ce soit il ne, juste les résultats, tout en familièrement, dire que vous voulez un processus transparent signifie que vous souhaitez que chaque partie d'être vu.map
au lieu deflatMap
, vous avez unStream<Stream<R>>
au lieu de seulement unStream<R>
gist.github.com/bradynpoulsen/f3f5458d718a996c5b3dec9decefb6d2flatMap
surmap
? Il semble que laflatMap
mappeur de déchets d'une étape en tournant le seul ensemble de valeurs d'entrée en plusieurs groupes pour les retourner en arrière en un seul ensemble dans la sortie.abcdefghijklmnopqrstuvwxyz
,0123456789
etc. Maintenant, vous voulez combiner ces alphabets dans une liste de caractères. Une possibilité serait de concaténer les chaînes et mettez le résultat dans une liste ou le flux de l'alphabet-la liste et utilisezflatMap
pour atteindre votre objectif, ce qui ne serait pas possible à l'aide demap
.Stream.flatMap
, comme on peut le deviner par son nom, est la combinaison d'unmap
et unflat
opération. Cela signifie que vous devez d'abord appliquer une fonction à vos éléments, et puis l'aplatir.Stream.map
ne s'applique qu'une fonction pour les flux sans l'aplatissement de la rivière.De comprendre ce aplatissement un flux consiste en, envisager une structure comme
[ [1,2,3],[4,5,6],[7,8,9] ]
qui a "deux niveaux". L'aplatissement cela signifie en le transformant en un "niveau" de la structure :[ 1,2,3,4,5,6,7,8,9 ]
.Je voudrais donner 2 exemples pour obtenir un plus point de vue pratique:
Premier exemple, l'utilisation de la carte:
Rien de spécial dans le premier exemple, un
Function
est demandé à retourner laString
en majuscules.Deuxième exemple, l'utilisation de
flatMap
:Dans le deuxième exemple, un Flux de Liste est transmise. Il n'est PAS un Flux de Entier!
Si une Fonction de transformation doit être utilisé (par le biais de la carte), puis la première à diffuser le Flux aplatie à quelque chose d'autre (un Flux de type Entier).
Si flatMap est supprimé le message d'erreur suivant est renvoyé: L'opérateur + est pas défini pour le type d'argument(s) de la Liste, int.
Il n'est PAS possible d'appliquer des + 1 sur une Liste d'Entiers!
S'il vous plaît aller à travers le poste entièrement pour se faire une idée claire,
carte vs flatMap:
Pour revenir à une longueur de chaque mot dans une liste, nous ferions quelque chose comme ci-dessous..
Version courte étant donné ci-dessous
Lorsque nous recueillons des deux listes, donnée ci-dessous
Sans plat de la carte => [1,2],[1,1] => [[1,2],[1,1]] Ici, deux listes sont placés à l'intérieur d'une liste, de sorte que la sortie sera liste contenant des listes
Avec plat de la carte => [1,2],[1,1] => [1,2,1,1] Ici deux listes sont aplaties et seules les valeurs sont placées dans la liste, de sorte que la sortie sera liste ne contenant que des éléments
Fondamentalement, il fusionne tous les objets dans one
## Version détaillée a été donnée ci-dessous:-
Par exemple:-
tenir compte d'une liste [“PILE”, ”OOOVVVER”] et nous essayons de revenir une liste comme [“STACKOVER”](retour uniquement unique des lettres à partir de cette liste)
D'abord, nous voudrions faire quelque chose comme ci-dessous pour retourner une liste [“STACKOVER”] de [“PILE”, ”OOOVVVER”]
Ici la question est, Lambda passé la carte de la méthode retourne un tableau de chaînes, pour chaque mot, de Sorte que le flux retourné par la méthode map est en fait de type de Flux, Mais nous avons besoin de Flux de représenter un flux de caractères, l'image ci-dessous illustre le problème.
Figure A:
Vous pourriez penser que, Nous pouvons résoudre ce problème en utilisant flatmap,
OK, nous allons voir comment résoudre ce problème en utilisant carte et Tableaux.flux
Tout d'abord, vous allez avoir besoin d'un flux de caractères au lieu d'un flux de tableaux. Il existe une méthode appelée Tableaux.stream() qui prend un tableau et produit un flux de données, par exemple:
Le ci-dessus ne fonctionne toujours pas, car nous avons maintenant jusqu'à la fin avec une liste de cours d'eau (plus précisément, Flux>), au Lieu de cela, nous devons d'abord convertir chaque mot dans un tableau de lettres, puis faire de chaque tableau dans un flux séparé
En utilisant flatMap nous devrions être en mesure de résoudre ce problème tant que ci-dessous:
flatMap effectuer la cartographie de chaque tableau pas de stream, mais avec le contenu de ce cours d'eau. Tous les flux individuels qui serait généré lors de l'utilisation de la carte(les Tableaux::stream) sont fusionnés en un seul flux. La Figure B montre l'effet de l'utilisation de la flatMap méthode. Comparer avec ce que la carte ne figure A.
Figure B
La flatMap méthode permet de remplacer chaque valeur d'un ruisseau avec un autre flux, puis rejoint l'ensemble de l'généré des flux en un seul flux.
Une ligne de réponse:
flatMap
aide à aplatir unCollection<Collection<T>>
dans unCollection<T>
. De la même manière, il sera également aplatir unOptional<Optional<T>>
enOptional<T>
.Comme vous pouvez le voir, avec
map()
seulement:Stream<List<Item>>
List<List<Item>>
et avec
flatMap()
:Stream<Item>
List<Item>
C'est le résultat du test du code ci-dessous à droite:
Code utilisé:
La fonction que vous passez à
stream.map
doit retourner un objet. Cela signifie que chaque objet dans le flux d'entrée des résultats dans exactement un objet dans le flux de sortie.La fonction que vous passez à
stream.flatMap
renvoie un flux pour chaque objet. Cela signifie que la fonction peut renvoyer n'importe quel nombre d'objets pour chaque objet entrée (y compris aucune). La conséquence, les flux sont ensuite concaténées à un flux de sortie.Department
s dans votre organisation. Chaque département a entre 0 et nEmployee
s. Ce que vous avez besoin est un courant de tous les employés. Alors que faites-vous? Vous écrivez un flatMap méthode qui prend un département et renvoie un flux de ses employés.flatMap
? Je soupçonne qu'il pourrait être accessoire et n'est pas d'illustrer les principaux cas d'utilisation ou la raison pourquoiflatMap
existe. (Suite ci-dessous...)flatMap
est de tenir compte des erreurs qui seraient présents lors de l'utilisation demap
. Comment avez-vous gérer les cas où un ou plusieurs éléments dans le jeu d'origine ne peut pas être mappé à un élément de sortie? Par l'introduction d'un intermédiaire set (dire unOptional
ouStream
) pour chaque entrée de l'objet,flatMap
vous permet d'exclure les "invalides" objets d'entrée (ou de la soi-disant "pommes pourries" dans l'esprit de stackoverflow.com/a/52248643/107158) de l'ensemble final.pour une Carte nous avons une liste d'éléments et d'une (fonction,action) f donc :
et pour le plat de la carte, nous avons une liste des éléments de liste et nous avons une (fonction,action) f et nous voulons que le résultat d'être aplatie :
J'ai le sentiment que la plupart des réponses ici compliquer le problème simple. Si vous comprenez déjà comment le
map
œuvres qui devrait être assez facile à saisir.Il y a des cas où on peut se retrouver avec des structures imbriquées lors de l'utilisation de
map()
, leflatMap()
méthode est destinée à résoudre ce problème en évitant d'emballage.Exemples:
1
Nous pouvons éviter d'avoir des listes imbriquées en utilisant
flatMap
:2
où:
List<Integer> result = Stream.of(Arrays.asList(1), Arrays.asList(2, 3)) .flatMap(i -> i) .collect(Collectors.toList());
. Il doit êtreStream.of(Arrays.asList(1), Arrays.asList(2, 3)) .flatMap(List::stream) .collect(Collectors.toList());
Oracle article sur les faits saillants en Option cette différence entre la carte et flatmap:
http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html
Optional
s, si lagetter
le retour deOptional
s, alors maintenantNullPointerException
sera levée.Je ne suis pas très sûr que je suis censé répondre à cette question, mais à chaque fois que je fais face à quelqu'un qui ne comprend pas cela, j'utilise le même exemple.
Imaginez que vous avez un apple. Un
map
est que la transformation de la pomme deapple-juice
, par exemple, ou un un-à-un de cartographie.Prendre que même apple et d'obtenir seulement les graines en dehors de ça, c'est ce que
flatMap
n', ou un un à plusieurs, une pomme comme entrée, beaucoup de graines en sortie.flatMap
cas, avez-vous d'abord collecter les graines de chaque pomme dans des sacs, un sac par apple, avant de vous verser tous les sacs dans un seul sac?flatmap
n'était pas vraiment paresseux, mais depuis java-10, il est paresseuxflatMap + lazy
, je parie qu'il y aura quelques réponses.Carte:-
Cette méthode prend une Fonction en argument et renvoie un nouveau flux de données comprenant les résultats générés par l'application de la fonction à tous les éléments du flux.
Imaginons, j'ai une liste de valeurs de type entier ( 1,2,3,4,5 ) et une fonction d'interface dont la logique est la place de l'transmis entier. ( e -> e * e ).
de sortie:-
Comme vous pouvez le voir, une sortie est un nouveau flux de données dont les valeurs sont des carrés des valeurs du flux d'entrée.
http://codedestine.com/java-8-stream-map-method/
FlatMap :-
Cette méthode prend une Fonction comme argument, cette fonction accepte un paramètre T comme un argument en entrée et renvoie un flux de paramètre R comme une valeur de retour. Lorsque cette fonction est appliquée à chaque élément de ce courant, il produit un flux de nouvelles valeurs. Tous les éléments de ces nouveaux flux générés par chaque élément sont alors copiés dans un nouveau flux de données, qui sera une valeur de retour de cette méthode.
Laisser de l'image, j'ai une liste d'objets student, où chaque étudiant peut opter pour plusieurs sujets.
de sortie:-
Comme vous pouvez le voir, une sortie est un nouveau flux de données dont les valeurs sont une collection de tous les éléments du flux de retour par chaque élément du flux d'entrée.
[ S1 , S2 , S3 ] ->
[ {"histoire","mathématiques","géographie"}, {"economie","biologie"}, {"science","mathématiques"} ] -> prendre unique sujets ->
[économie, la biologie, la géographie, les sciences, l'histoire, les mathématiques]
http://codedestine.com/java-8-stream-flatmap-method/
map() et flatMap()
map()
Prend juste une Fonction lambda param où T est l'élément et R le retour de l'élément construit à l'aide de T. À la fin, nous aurons un Ruisseau avec des objets de Type R. Un exemple simple peut être:
Il suffit d'éléments de 1 à 5 de Type
Integer
, utilise chaque élément de construire un nouvel élément de typeString
avec la valeur"prefix_"+integer_value
et l'imprime sur.flatMap()
Il est utile de savoir que flapMap() prend une fonction
F<T, R>
oùT est un type de laquelle un cours d'eau peut être construit à partir de/avec. Il peut être une Liste (T. stream()), un tableau (Tableaux.flux(someArray)), etc.. tout ce qui à partir de laquelle un Flux peut être avec/ou de la forme. dans l'exemple ci-dessous chaque dev a beaucoup de langues, afin de dev. Langues est une Liste, et d'utiliser un paramètre lambda.
R est le Flux qui va être construit à l'aide de T. Sachant que nous avons de nombreux cas de T, on aura naturellement de nombreux cours d'eau de R. l'Ensemble de ces Flux de Type R ne maintenant être combinés en un seul unique "à plat" un Flux de Type R.
Exemple
Les exemples de Bachiri Taoufiq voir sa réponse ici sont simples et faciles à comprendre. Juste pour plus de clarté, laissez simplement de dire que nous avons une équipe de développeurs:
avec à chaque développeur de connaître plusieurs langues:
L'Application De Flux.map() sur dev_team pour obtenir les langues de chaque dev:
vous donnera cette structure:
qui est essentiellement un
List<List<Languages>> /Object[Languages[]]
. Pas très joli, ni Java8 comme!!avec
Stream.flatMap()
vous pouvez "aplatir" les choses comme il faut de la structure ci-dessuset il se transforme en
{lang_a, lang_b, lang_c, lang_d, lang_e, lang_f}
, qui peut être simplement utilisé commeList<Languages>/Language[]/ect
...de sorte que la fin de votre code aurait plus de sens comme ça:
ou tout simplement:
Lors de l'utilisation de la carte() et utiliser flatMap():
Utilisation
map()
lorsque chaque élément de type T à partir de votre flux est censé être mappé/transformées à un unique élément de type R. Le résultat est un mappage de type (1 élément de début -> 1 élément de fin) et de nouveaux flux d'éléments de type R est retourné.Utilisation
flatMap()
lorsque chaque élément de type T à partir de votre flux est censé mappé/transformées à un Collections d'éléments de type R. Le résultat est un mappage de type (1 élément de début -> n la fin des éléments). Ces Collections sont ensuite fusionné (ou aplatie) à un nouveau flux d'éléments de type R. C'est utile par exemple pour représenter boucles imbriquées.Avant Java 8:
Post Java 8
Aussi bonne analogie peut être avec C# si vous familiariser avec. Fondamentalement, C#
Select
similaire à javamap
et C#SelectMany
javaflatMap
. Même s'applique à Kotlin pour les collections.C'est très déroutant pour les débutants. La différence de base est
map
émet un élément pour chaque entrée dans la liste etflatMap
est fondamentalement unmap
+flatten
opération. Pour être plus clair, l'utilisation flatMap lorsque vous avez besoin de plus d'une valeur, par exemple, lorsque vous vous attendez à une boucle de retour des tableaux, flatMap sera vraiment utile dans ce cas.J'ai écrit un blog à ce sujet, vous pouvez le vérifier ici.
De réponse Simple.
La
map
opération peut produire unStream
deStream
.EXStream<Stream<Integer>>
flatMap
opération n'produireStream
de quelque chose. EXStream<Integer>
Flux des opérations de
flatMap
etmap
accepter une fonction d'entrée.flatMap
s'attend à ce que la fonction de retour d'un nouveau flux de données pour chaque élément du flux et renvoie un flux de données qui combine tous les éléments du flux renvoyé par la fonction de chaque élément. En d'autres termes, avecflatMap
, pour chaque élément de la source, plusieurs éléments seront créés par la fonction. http://www.zoftino.com/java-stream-examples#flatmap-operationmap
s'attend à ce que la fonction de retour de la transformation de la valeur et renvoie un nouveau flux contenant de la transformation des éléments. En d'autres termes, avecmap
, pour chaque élément de la source, on a transformé élément sera créé par la fonction.http://www.zoftino.com/java-stream-examples#map-operation
flatMap()
tire également parti de l'partielle paresseux évaluation des cours d'eau. Il va lire le poing flux et seulement lorsque nécessaire, passera à la prochaine stream. Le comportement est expliqué en détail ici: Est flatMap la garantie d'être paresseux?map() en Java 8
un flux de données comprenant les résultats de l'application de la fonction donnée aux éléments de ce flux. La carte prend une entrée qui décrit la façon dont la valeur doit être transformée en.
Supposons que nous voulons obtenir de l'âge de l'Étudiant dont le nom est Saurabh, jusqu'à maintenant, nous avons seulement récupéré l'objet, à partir du flux mais comment faisons-nous cela ?
Nous pouvons utiliser la carte() pour transformer l'Étudiant Ruisseau jusqu'à l'âge de flux ci-dessous.
Permet maintenant essayer d'obtenir tous les noms des élèves avec l'aide de collect()
map() vs flatMap()
Supposons que nous voulons récupérer tous les cours disponibles dans les étudiants de la liste alors nous pouvons écrire le code comme ci-dessous:
**Ici, nous allons obtenir une erreur de compilation comme ci-dessous
Incompatibilité de Type: impossible de convertir de Définir à Définir
Pour résoudre ce problème, nous utilisons flatMap()**
flatMap() en Java 8
Il renvoie un flux de données comprenant les résultats de remplacer chaque élément de ce flux avec le contenu d'un mappage de flux produit par l'application de la condition de la cartographie de la fonction de chaque élément.
flatMap va transformer le flux de flux de données en simple flux. Dans l'exemple ci-dessous, nous utilisons la flatMap pour convertir le Tableau de Flux dans la Chaîne de stream.
Pour plus d'informations vous pouvez vous référer aux liens ci-dessous :
https://onlyfullstack.blogspot.com/2018/12/map-vs-flatmap-in-java-8.html
http://onlyfullstack.blogspot.com/p/java-8-features.html