Angenommen, ich habe einen Datenstrom von Dingen und möchte diese in der Mitte des Datenstroms "anreichern". peek()
Dazu kann ich Folgendes verwenden :
streamOfThings.peek(this::thingMutator).forEach(this::someConsumer);
Nehmen Sie an, dass das Mutieren der Dinge an dieser Stelle im Code korrekt ist - zum Beispiel das thingMutator
Methode das Feld "lastProcessed" möglicherweise auf die aktuelle Zeit.
Jedoch, peek()
meisten Kontexten bedeutet es jedoch "schauen, aber nicht anfassen".
Ist die Verwendung peek()
zum Mutieren von Stream-Elementen ein Gegenmuster oder eine schlechte Empfehlung?
Bearbeiten:
Der alternative, konventionellere Ansatz wäre die Umstellung des Verbrauchers:
private void thingMutator(Thing thing) {
thing.setLastProcessed(System.currentTimeMillis());
}
zu einer Funktion, die den Parameter zurückgibt:
private Thing thingMutator(Thing thing) {
thing.setLastProcessed(currentTimeMillis());
return thing;
}
und benutze map()
stattdessen:
stream.map(this::thingMutator)...
Aber das einleitet perfunctory Code ( return
) und ich bin nicht davon überzeugt , es ist klarer, weil Sie wissen , peek()
kehren das gleiche Objekt, aber mit map()
ihm nicht einmal auf einem Blick klar ist , dass es die gleiche Klasse des Objekts.
Weiter kann mit peek()
dir ein Lambda sein, das mutiert, aber mit map()
dir musst du ein Zugunglück bauen. Vergleichen Sie:
stream.peek(t -> t.setLastProcessed(currentTimeMillis())).forEach(...)
stream.map(t -> {t.setLastProcessed(currentTimeMillis()); return t;}).forEach(...)
Ich denke der peek()
Version ist klarer und das Lambda mutiert eindeutig, so dass es keine "mysteriösen" Nebenwirkungen gibt. In ähnlicher Weise ist auch dies klar und offensichtlich, wenn eine Methodenreferenz verwendet wird und der Name der Methode eindeutig eine Mutation impliziert.
Persönlich scheue ich mich nicht davor, peek()
zu mutieren - ich finde es sehr praktisch.
peek
mit einem Stream gearbeitet, der seine Elemente dynamisch generiert? Funktioniert es noch oder gehen die Änderungen verloren? Das Ändern der Elemente eines Streams klingt für mich unzuverlässig.
List<Thing> list; things.stream().peek(list::add).forEach(...);
sehr praktisch. In letzter Zeit. Ich habe es verwendet Infos hinzufügen für die Veröffentlichung: Map<Thing, Long> timestamps = ...; return things.stream().peek(t -> t.setTimestamp(timestamp.get(t))).collect(toList());
. Ich weiß, dass es andere Möglichkeiten gibt, dieses Beispiel umzusetzen, aber ich vereinfache es hier stark. Mit peek()
kompakter und eleganter Code IMHO. Abgesehen von der Lesbarkeit handelt es sich bei dieser Frage wirklich um das, was Sie angesprochen haben. Ist es sicher / zuverlässig?
peek
? Ich habe eine ähnliche Frage zum Stackoverflow und hoffe, Sie könnten es sich ansehen und Ihr Feedback geben. Vielen Dank. stackoverflow.com/questions/47356992/…