En Java, existe-t-il un moyen d'appliquer une fonction à tous les éléments d'un flux sans rompre la chaîne de flux? Je sais que je peux appeler forEach, mais cette méthode renvoie un vide, pas un flux.Java 8 applique la fonction à tous les éléments de Stream sans rompre la chaîne de flux
Répondre
Vous recherchez la fonction map()
de Stream
.
exemple:
List<String> strings = stream
.map(Object::toString)
.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
Si j'utilise une carte, je devrai utiliser plusieurs lignes. quelque chose comme myStream.map (obj -> {obj.foo(); return obj;}). Je me demandais s'il y a une solution d'une ligne à cela. – alexgbelov
Vous pouvez également y référer une méthode, vérifiez mon mod. – csenga
Je pense que vous cherchez Stream.peek
. Mais lisez attentivement les documents, car il a été conçu principalement comme une méthode de débogage. A partir de la documentation:
Cette méthode existe principalement pour soutenir le débogage, où vous voulez voir les éléments comme ils coulent passé un certain point dans un pipeline
L'action passée à peek
doit être non interfering.
Pas tout à fait sûr de ce que vous entendez par breaking the stream chain
, mais toute opération sur un Stream
qui retourne une Stream
ne sera pas pause ou consommer votre flux. Les flux sont consommés par terminal operations
et comme vous l'avez noté le forEach
ne renvoie pas un Stream<T>
et en tant que tel termine le flux, en exécutant toutes les opérations intermediate
avant le forEach et le forEach lui-même.
Dans l'exemple que vous avez fourni dans les commentaires:
myStream.map(obj -> {obj.foo(); return obj;}
Vous ne pouvez pas vraiment faire cela avec une doublure. Bien sûr, vous pouvez utiliser une référence de méthode, mais votre retour Stream
serait d'un type différent (en supposant foo
retourne un type):
myStream.map(Obj::foo) // this will turn into Stream<T>, where T is
// the return type of foo, instead of Stream<Obj>
Outre que votre opération map
est stateful
, qui est fortement déconseillée. Votre code compilera et pourrait même fonctionner comme vous le souhaitez - mais il pourrait échouer plus tard. Les opérations map
doivent être stateless
.
Il y a (au moins) 3 façons. Par souci de code exemple, je l'ai supposé que vous voulez appeler 2 méthodes de consommation methodA
et methodB
:
A. Utilisez peek()
:
list.stream().peek(x -> methodA(x)).forEach(x -> methodB(x));
Bien que les documents disent ne l'utiliser que pour « debug », cela fonctionne (et il est dans la production en ce moment)
B. Utilisez map()
pour appeler methodA, puis revenir en arrière l'élément au courant:
list.stream().map(x -> {method1(x); return x;}).forEach(x -> methodB(x));
C'est probablement l'approche la plus "acceptable".
C.Deux choses dans le forEach()
:
list.stream().forEach(x -> {method1(x); methodB(x);});
Ceci est la moins flexible et peut ne pas convenir à vos besoins.
Les implications de l'exécution d'une action avec des effets secondaires dans la fonction 'map' et l'utilisation de' peek' pour un tel effet secondaire (non-debug) sont fondamentalement les mêmes. – Holger
@Holger qui a dit quelque chose au sujet des effets secondaires? – Bohemian
L'invocation de 'method1 (x);' serait totalement inutile si elle n'avait pas d'effets secondaires. – Holger
La meilleure option que vous avez est d'appliquer la carte à votre flux. qui renvoie un flux constitué par les résultats de l'application de la donnée, la fonction des éléments de ce courant par exemple:
IntStream.rangeClosed(40, 70).limit(20).mapToObj(i -> (Integer) i).map(item->item+3).map(item->item*2)...
(jet d'articles de type StreamItemABC)
Nous appliquons plusieurs modifications dans le flux mais de cette façon, nous ne pouvons passer aucun argument à la méthode map, pour le réparer:
private void applyMethod(ParameterX parX) {
someStreamX().map(n -> methodX(n, parX))...
}
private StreamItemABC methodX (StreamItemABC item, ParameterX parX) {
return notification;
}
La méthode que vous voulez appeler renvoie-t-elle une valeur? –
pouvez-vous expliquer ce que vous entendez par «sans rompre la chaîne de flux»? peut être un exemple? – Eugene