Supposons que j'ai un flux de choses et que je veuille les "enrichir" à mi-parcours, je peux utiliser peek()
ceci, par exemple:
streamOfThings.peek(this::thingMutator).forEach(this::someConsumer);
Supposons que la mutation des objets à ce stade du code constitue un comportement correct. Par exemple, la thingMutator
méthode peut définir le champ "lastProcessed" à l'heure actuelle.
Cependant, peek()
dans la plupart des contextes, cela signifie "regarde, mais ne touche pas".
L'utilisation peek()
de la mutation d' éléments de flux est-elle un anti-modèle ou une mauvaise idée?
Modifier:
L’approche alternative, plus conventionnelle, consisterait à convertir le consommateur:
private void thingMutator(Thing thing) {
thing.setLastProcessed(System.currentTimeMillis());
}
à une fonction qui retourne le paramètre:
private Thing thingMutator(Thing thing) {
thing.setLastProcessed(currentTimeMillis());
return thing;
}
et utilisez map()
plutôt:
stream.map(this::thingMutator)...
Mais cela introduit un code superficiel (le return
) et je ne suis pas convaincu que ce soit plus clair, car vous savez qu'il peek()
retourne le même objet, mais map()
il n'est même pas évident en un coup d'œil qu'il s'agisse de la même classe d'objet.
De plus, avec peek()
vous , vous pouvez avoir un lambda qui mute, mais avec map()
vous, vous devez construire une épave de train. Comparer:
stream.peek(t -> t.setLastProcessed(currentTimeMillis())).forEach(...)
stream.map(t -> {t.setLastProcessed(currentTimeMillis()); return t;}).forEach(...)
Je pense que la peek()
version est plus claire et que le lambda est en train de muter, il n’ya donc pas d’effet secondaire "mystérieux". De même, si une référence de méthode est utilisée et que le nom de la méthode implique clairement une mutation, cela aussi est clair et évident.
Sur une note personnelle, je n'hésite pas à utiliser peek()
pour muter - je trouve cela très pratique.
peek
avec un flux qui génère ses éléments de manière dynamique? Cela fonctionne-t-il toujours ou les modifications sont-elles perdues? La modification des éléments d'un flux ne me semble pas fiable.
List<Thing> list; things.stream().peek(list::add).forEach(...);
très pratique. Dernièrement. Je l' ai utilisé pour ajouter des informations pour la publication: Map<Thing, Long> timestamps = ...; return things.stream().peek(t -> t.setTimestamp(timestamp.get(t))).collect(toList());
. Je sais qu'il existe d'autres façons de faire cet exemple, mais je simplifie énormément ici. Utilisation peek()
produit un code IMHO plus compact et plus élégant. La lisibilité mise à part, cette question concerne vraiment ce que vous avez soulevé; est-ce sûr / fiable?
peek
? J'ai une question similaire sur stackoverflow et j'espère que vous pourrez l'examiner et donner votre avis. Merci. stackoverflow.com/questions/47356992/…