Припустимо, у мене є потік Речей, і я хочу "збагатити" їх середнім потоком, я можу використовувати peek()
це, наприклад:
streamOfThings.peek(this::thingMutator).forEach(this::someConsumer);
Припустимо, що мутація Речей у цьому пункті коду є правильною поведінкою - наприклад, thingMutator
метод може встановити поле "lastProcessed" на поточний час.
Однак peek()
у більшості контекстів означає "дивись, але не чіпай".
Користуємося peek()
для мутувати елементи потоку в антипаттерн або необачно?
Редагувати:
Альтернативним, більш традиційним, підходом було б перетворення споживача:
private void thingMutator(Thing thing) {
thing.setLastProcessed(System.currentTimeMillis());
}
до функції, яка повертає параметр:
private Thing thingMutator(Thing thing) {
thing.setLastProcessed(currentTimeMillis());
return thing;
}
і використовувати map()
замість цього:
stream.map(this::thingMutator)...
Але це вводить функціональний код (the return
), і я не переконаний, що це зрозуміліше, тому що ви знаєте, peek()
повертає той самий об'єкт, але з першого map()
погляду навіть не зрозуміло, що це той самий клас об'єктів.
Далі, у peek()
вас може бути лямбда, яка мутує, але з map()
вами доведеться побудувати аварію поїзда. Порівняйте:
stream.peek(t -> t.setLastProcessed(currentTimeMillis())).forEach(...)
stream.map(t -> {t.setLastProcessed(currentTimeMillis()); return t;}).forEach(...)
Я думаю, що peek()
версія зрозуміліша, а лямбда явно мутує, тому "загадкового" побічного ефекту немає. Аналогічно, якщо використовується посилання на метод, а назва методу чітко передбачає мутацію, це теж зрозуміло і очевидно.
В особистій записці я не цураюся використання peek()
мутації - мені здається, що це дуже зручно.
peek
потік, який динамічно генерує його елементи? Це все ще працює, або зміни втрачені? Змінення елементів потоку для мене звучить ненадійно.
List<Thing> list; things.stream().peek(list::add).forEach(...);
дуже зручно. Останнім часом. Я використовував його , щоб додати інформацію для публікації: Map<Thing, Long> timestamps = ...; return things.stream().peek(t -> t.setTimestamp(timestamp.get(t))).collect(toList());
. Я знаю, що є інші способи зробити цей приклад, але я тут сильно надто спрощую. Використання peek()
створює більш компактний і елегантний код IMHO. Читання убік, це питання справді стосується того, що ви підняли; це безпечно / надійно?
peek
? У мене є подібне запитання щодо stackoverflow, і сподіваюся, що ви могли це переглянути і дати свої відгуки. Спасибі. stackoverflow.com/questions/47356992 / ...