Załóżmy, że mam strumień Rzeczy i chcę je „wzbogacić” w połowie strumienia, mogę peek()
to zrobić, np .:
streamOfThings.peek(this::thingMutator).forEach(this::someConsumer);
Załóżmy, że mutowanie Rzeczy w tym punkcie kodu jest poprawnym zachowaniem - na przykład thingMutator
metoda może ustawić pole „lastProcessor” na bieżący czas.
Jednak peek()
w większości kontekstów oznacza „patrz, ale nie dotykaj”.
Używa peek()
się mutować elementów Stream antywzorzec projektowy lub nierozważne?
Edytować:
Alternatywnym, bardziej konwencjonalnym podejściem byłoby przekonanie konsumenta:
private void thingMutator(Thing thing) {
thing.setLastProcessed(System.currentTimeMillis());
}
do funkcji, która zwraca parametr:
private Thing thingMutator(Thing thing) {
thing.setLastProcessed(currentTimeMillis());
return thing;
}
i użyj map()
zamiast tego:
stream.map(this::thingMutator)...
Ale to wprowadza kod obłędny ( return
) i nie jestem przekonany, że jest bardziej przejrzysty, ponieważ wiesz, że peek()
zwraca ten sam obiekt, ale map()
na pierwszy rzut oka nie jest nawet jasne, że jest to ta sama klasa obiektu.
Co więcej, peek()
możesz mieć mutację lambda, ale wraz z map()
tobą musisz zbudować wrak pociągu. Porównać:
stream.peek(t -> t.setLastProcessed(currentTimeMillis())).forEach(...)
stream.map(t -> {t.setLastProcessed(currentTimeMillis()); return t;}).forEach(...)
Myślę, że peek()
wersja jest wyraźniejsza, a lambda wyraźnie mutuje, więc nie ma „tajemniczego” efektu ubocznego. Podobnie, jeśli używane jest odwołanie do metody, a nazwa metody wyraźnie implikuje mutację, to również jest jasne i oczywiste.
Osobiście nie waham się używać peek()
mutacji - uważam to za bardzo wygodne.
peek
ze strumienia, który dynamicznie generuje jego elementy? Czy to nadal działa, czy zmiany zostały utracone? Modyfikowanie elementów strumienia wydaje mi się niewiarygodne.
List<Thing> list; things.stream().peek(list::add).forEach(...);
bardzo przydatny. Ostatnio. Używałem go dodać informacje do publikacji: Map<Thing, Long> timestamps = ...; return things.stream().peek(t -> t.setTimestamp(timestamp.get(t))).collect(toList());
. Wiem, że istnieją inne sposoby na zrobienie tego przykładu, ale tutaj nadmiernie upraszczam. Korzystanie peek()
tworzy bardziej zwarty i bardziej elegancki kod IMHO. Pomijając czytelność, to pytanie naprawdę dotyczy tego, co poruszyłeś; czy to jest bezpieczne / niezawodne?
peek
? Mam podobne pytanie na temat przepełnienia stosu i mam nadzieję, że mógłbyś na nie spojrzeć i wyrazić swoją opinię. Dzięki. stackoverflow.com/questions/47356992/…