Tengo curiosidad por saber por qué Java opcional no proporciona un peek
método similar a Stream
uno 's .
El peek
método javadoc de los Stream
estados de interfaz:
- @apiNote Este método existe principalmente para la depuración de apoyo, en la que desea ver los elementos a medida que fluyen más allá de un cierto punto en una tubería
Esto describe casi exactamente mi caso de uso:
@Override
@Transactional
public User getUserById(long id) {
return repository.findById(id)
.peek(u -> logger.debug("Found user = {} by id = {}", u, id))
.orElseThrow(() -> new UserNotFoundException("id = " + id));
}
( repository.findById
Rendimientos Optional<User>
(ver CrudRepository # findById ))
Pero no va a compilar ya que no hay peek
método en Optional
.
Así que sin el peek
método de todo lo anterior se transforma en:
@Override
@Transactional
public User getUserById(long id) {
Optional<User> userOptional = repository.findById(id);
if (userOptional.isPresent()) {
logger.debug("Found user = {} with id = {}", userOptional.get(), id);
}
return userOptional.orElseThrow(() -> new UserNotFoundException("id = " + id));
}
También es posible hacer algo como esto (ver esta respuesta ):
@NoArgsConstructor(access = PRIVATE)
public abstract class OptionalUtils {
public static <T> UnaryOperator<T> peek(Consumer<T> consumer) {
return t -> {
consumer.accept(t);
return t;
};
}
}
Y utilizarlo con el map
método:
return repository.findById(id)
.map(OptionalUtils.peek(u -> logger.debug("Found user = {} with id = {}", u, id)))
.orElseThrow(() -> new UserNotFoundException("id = " + id));
Pero creo que esto es un corte limpio en lugar de uso de Optional
.
Desde Java 9 que es posible transformar Optional
a Stream
pero la corriente no tiene el orElseThrow
método (y, obviamente, no debería).
También es posible hacer lo mismo usando ifPresent
pero vuelve void
. (Y para mí, parece que ifPresent
no hay que volver otra cosa que no sea void
)
Estoy haciendo mal uso Optional
?
Es la ausencia de la peek
intencional método? (Pero, al mismo tiempo Vavr de Option
sí provee el peek
método).
O se considera simplemente no vale la pena?
Bueno, sólo los diseñadores podrían responder que los detalles "exacta" de por qué no existía un método peek para Opcionales.
Así que, por ahora, que está pegado con el uso de isPresent()
lo que en realidad parece muy bien en mi opinión:
if (userOptional.isPresent())
logger.debug("Found user = {} with id = {}", userOptional.get(), id);
o usted podría considerar las respuestas sugeridas en la página del enlace si lo desea, como parte de la tubería.
por cierto, dado el nuevo stream
método de JDK9 que podría hacer:
return repository.findById(id) // Optional<User>
.stream() // Stream<User>
.peek(u -> logger.debug("Found user = {} by id = {}", u, id)) // Stream<User>
.findFirst() // Optional<User>
.orElseThrow(() -> new UserNotFoundException("id = " + id))