Suponha que eu tenha um fluxo de coisas e que queira "enriquecê-los" no meio do fluxo, posso usar peek()
isso, por exemplo:
streamOfThings.peek(this::thingMutator).forEach(this::someConsumer);
Suponha que a alteração das coisas neste momento no código seja um comportamento correto - por exemplo, o thingMutator
método pode definir o campo "lastProcessed" para o horário atual.
No entanto, peek()
na maioria dos contextos significa "olhe, mas não toque".
O uso peek()
para alterar elementos de fluxo é um antipadrão ou é desaconselhável?
Editar:
A abordagem alternativa, mais convencional, seria converter o consumidor:
private void thingMutator(Thing thing) {
thing.setLastProcessed(System.currentTimeMillis());
}
para uma função que retorna o parâmetro:
private Thing thingMutator(Thing thing) {
thing.setLastProcessed(currentTimeMillis());
return thing;
}
e use map()
:
stream.map(this::thingMutator)...
Mas isso introduz código superficial (the return
) e não estou convencido de que seja mais claro, porque você sabe que peek()
retorna o mesmo objeto, mas com map()
isso nem fica claro à primeira vista que é a mesma classe de objeto.
Além disso, peek()
você pode ter um lambda que sofre mutação, mas com map()
você tem que construir um acidente de trem. Comparar:
stream.peek(t -> t.setLastProcessed(currentTimeMillis())).forEach(...)
stream.map(t -> {t.setLastProcessed(currentTimeMillis()); return t;}).forEach(...)
Eu acho que a peek()
versão é mais clara e o lambda está claramente mudando, então não há efeito colateral "misterioso". Da mesma forma, se uma referência de método for usada e o nome do método implicar claramente uma mutação, isso também será claro e óbvio.
Em uma nota pessoal, não evito usar o peek()
mutate - acho muito conveniente.
peek
com um fluxo que gera seus elementos dinamicamente? Ainda funciona ou as alterações são perdidas? Modificar os elementos de um fluxo parece pouco confiável para mim.
List<Thing> list; things.stream().peek(list::add).forEach(...);
muito útil. Recentemente. Eu usei-o para adicionar informações para a publicação: Map<Thing, Long> timestamps = ...; return things.stream().peek(t -> t.setTimestamp(timestamp.get(t))).collect(toList());
. Eu sei que existem outras maneiras de fazer esse exemplo, mas estou simplificando bastante aqui. Usar peek()
produz código IMHO mais compacto e mais elegante. Legibilidade à parte, esta questão é realmente sobre o que você levantou; é seguro / confiável?
peek
? Tenho uma pergunta semelhante sobre o stackoverflow e espero que você possa ver e dar seu feedback. Obrigado. stackoverflow.com/questions/47356992/…