java - Uso adecuado de Optional.ifPresent()
optional java (4)
Estoy intentando comprender el método ifPresent()
de la API Optional
en Java 8.
Tengo una lógica simple:
Optional<User> user=...
user.ifPresent(doSomethingWithUser(user.get()));
Pero esto da como resultado un error de compilación:
ifPresent(java.util.functionError:(186, 74) java: ''void'' type not allowed here)
Por supuesto que puedo hacer algo como esto:
if(user.isPresent())
{
doSomethingWithUser(user.get());
}
Pero esto es exactamente como un cheque null
desordenado.
Si cambio el código a este:
user.ifPresent(new Consumer<User>() {
@Override public void accept(User user) {
doSomethingWithUser(user.get());
}
});
El código se está volviendo más sucio, lo que me hace pensar en volver al viejo cheque null
.
¿Algunas ideas?
Además de la respuesta de @JBNizet, mi caso de uso general para ifPresent es combinar .isPresent()
y .get()
:
Vieja forma:
Optional opt = getIntOptional();
if(opt.isPresent()) {
Integer value = opt.get();
// do something with value
}
Nueva manera:
Optional opt = getIntOptional();
opt.ifPresent(value -> {
// do something with value
})
Esto, para mí, es más intuitivo.
Necesitas usarlo así:
user.ifPresent(ClassNameWhereMethodIs::doSomethingWithUser);
Método ifPresent()
obtiene el objeto Consumer
como un parámetro y (desde JavaDoc ): "Si hay un valor presente, invoque al consumidor especificado con el valor". El valor es su user
variable.
Use flatMap. Si hay un valor presente, flatMap devuelve una secuencia secuencial que contiene solo ese valor, de lo contrario devuelve una secuencia vacía. Por lo tanto, no es necesario utilizar ifPresent()
. Ejemplo:
list.stream().map(data -> data.getSomeValue).map(this::getOptinalValue).flatMap(Optional::stream).collect(Collectors.toList());
Optional<User>.ifPresent()
toma un Consumer<? super User>
Consumer<? super User>
como argumento. Le está pasando una expresión cuyo tipo es vacío. Entonces eso no compila.
Un consumidor debe implementarse como una expresión lambda:
Optional<User> user = ...
user.ifPresent(theUser -> doSomethingWithUser(theUser));
O incluso más simple, usando una referencia de método:
Optional<User> user = ...
user.ifPresent(this::doSomethingWithUser);
Esto es básicamente lo mismo que
Optional<User> user = ...
user.ifPresent(new Consumer<User>() {
@Override
public void accept(User theUser) {
doSomethingWithUser(theUser);
}
});
La idea es que la llamada al método doSomethingWithUser()
solo se ejecutará si el usuario está presente. Su código ejecuta directamente la llamada al método e intenta pasar su resultado de voir a ifPresent()
.