En Java 8, quiero hacer algo a un Optional
objeto si está presente, y hacer otra cosa si no está presente.
if (opt.isPresent()) {
System.out.println("found");
} else {
System.out.println("Not found");
}
Sin embargo, este no es un 'estilo funcional'.
Optional
tiene un ifPresent()
método, pero no puedo encadenar un orElse()
método.
Por lo tanto, no puedo escribir:
opt.ifPresent( x -> System.out.println("found " + x))
.orElse( System.out.println("NOT FOUND"));
En respuesta a @assylias, no creo que Optional.map()
funcione para el siguiente caso:
opt.map( o -> {
System.out.println("while opt is present...");
o.setProperty(xxx);
dao.update(o);
return null;
}).orElseGet( () -> {
System.out.println("create new obj");
dao.save(new obj);
return null;
});
En este caso, cuando opt
está presente, actualizo su propiedad y la guardo en la base de datos. Cuando no está disponible, creo uno nuevo obj
y lo guardo en la base de datos.
Nota en las dos lambdas tengo que volver null
.
Pero cuando opt
está presente, ambas lambdas se ejecutarán. obj
se actualizará y se guardará un nuevo objeto en la base de datos. Esto se debe return null
a la primera lambda. Y orElseGet()
continuará ejecutándose.
fuente
return null;
conreturn o;
(ambos). Sin embargo, tengo la fuerte sensación de que estás trabajando en el lugar equivocado. Deberías trabajar en el sitio que produjo esoOptional
. En ese lugar debe haber una forma de realizar la operación deseada sin el intermedioOptional
.ifPresent
esto contradice esto. Todos los demás métodos se refieren al valor y no a las acciones.Respuestas:
Para mí, la respuesta de @Dane White está bien, primero no me gustó usar Runnable pero no pude encontrar ninguna alternativa, aquí otra implementación que preferí más
Luego :
Actualización 1:
la solución anterior para la forma tradicional de desarrollo cuando tiene el valor y desea procesarlo, pero qué pasa si quiero definir la funcionalidad y la ejecución será entonces, verifique la mejora a continuación;
Entonces podría usarse como:
En este nuevo código tienes 3 cosas:
por cierto, ahora su nombre es más descriptivo, en realidad es Consumidor>
fuente
Si está utilizando Java 9+, puede usar el
ifPresentOrElse()
método:fuente
Java 9 presenta
ifPresentOrElse si hay un valor presente, realiza la acción dada con el valor, de lo contrario realiza la acción basada en vacío dada.
Ver excelente Opcional en Java 8 hoja de trucos .
Proporciona todas las respuestas para la mayoría de los casos de uso.
Breve resumen a continuación
ifPresent (): hace algo cuando se establece Opcional
filter () - rechazar (filtrar) ciertos valores opcionales.
map () - transforma el valor si está presente
orElse () / orElseGet (): se vuelve vacío Opcional al valor predeterminado T
orElseThrow () - lanza perezosamente excepciones en vacío Opcional
fuente
map
, pero es un poco extraño pedir una solución funcional para que pueda llamar a un DAO. Me parece que tendría más sentido devolver el objeto actualizado / nuevo de estemap.orElse
bloque y luego hacer lo que necesita hacer con el objeto devuelto.map
enfoca en la secuencia en sí y no está destinado a "hacer cosas a otro objeto dependiendo del estado de este elemento en la secuencia". Es bueno saber queifPresentOrElse
se agrega en Java 9.Una alternativa es:
Sin embargo, no creo que mejore la legibilidad.
O como sugirió Marko, use un operador ternario:
fuente
new Object();
en su primer lambda, pero para ser honesto, eso se vuelve muy feo. Me quedaría con un if / else para su ejemplo actualizado.map
para regresar soloOptional
para encadenar hace que el código sea más difícil de entender, mientras quemap
se supone que literalmente se asigna a algo.Otra solución sería utilizar funciones de orden superior de la siguiente manera
fuente
value -> () -> syso
significa la parte.String result = opt.map(value -> "withOptional").orElse("without optional");
No hay una excelente manera de hacerlo de forma inmediata. Si desea utilizar su sintaxis más limpia de forma regular, puede crear una clase de utilidad para ayudar:
Luego puede usar una importación estática en otro lugar para obtener una sintaxis cercana a la que busca:
fuente
Optional.ifPresentOrElse()
ha sido agregado a JDK 9.Si solo puede usar Java 8 o inferior:
1) si no tienes
spring-data
la mejor manera hasta ahora es:Ahora sé que no es tan legible e incluso difícil de entender para alguien, pero personalmente me parece bien y no veo otra forma fluida para este caso.
2) si tienes la suerte y puedes usar
spring-data
la mejor manera es Opcional # ifPresentOrElse :Si puede usar Java 9, definitivamente debería usar:
fuente
El comportamiento descrito se puede lograr mediante el uso de Vavr (anteriormente conocido como Javaslang), una biblioteca de objetos funcionales para Java 8+, que implementa la mayoría de las construcciones de Scala (siendo Scala un lenguaje más expresivo con un sistema de tipos mucho más rico construido en JVM). Es una muy buena biblioteca para agregar a sus proyectos Java para escribir código funcional puro.
Vavr proporciona la
Option
mónada que proporciona funciones para trabajar con el tipo de opción, como:fold
: para asignar el valor de la opción en ambos casos (definido / vacío)onEmpty
: permite ejecutar unaRunnable
opción cuando está vacíapeek
: permite consumir el valor de la opción (cuando se define).Serializable
lo contrario, loOptional
que significa que puede usarlo con seguridad como argumento de método y miembro de instancia.La opción sigue las leyes de la mónada en diferencia con la "pseudo-mónada" opcional de Java y proporciona una API más rica. Y, por supuesto, puede hacerlo desde un Opcional de Java (y
Option.ofOptional(javaOptional)
viceversa ): –Vavr se centra en la interoperabilidad.Yendo al ejemplo:
Otras lecturas
Referencia nula, el error de mil millones de dólares
NB Este es solo un muy pequeño ejemplo de lo que ofrece Vavr (coincidencia de patrones, secuencias también conocidas como listas perezosas evaluadas, tipos monádicos, colecciones inmutables, ...).
fuente
Otra solución podría ser la siguiente:
Así es como lo usas:
O en caso de que en el caso de uso contrario sea cierto:
Estos son los ingredientes:
La interfaz de funciones mejorada "cosméticamente".
Y la clase de contenedor opcional para mejora:
Esto debería hacer el truco y podría servir como una plantilla básica sobre cómo lidiar con tales requisitos.
La idea básica aquí es la siguiente. En un mundo de programación de estilo no funcional, probablemente implementaría un método que toma dos parámetros donde el primero es un tipo de código ejecutable que debe ejecutarse en caso de que el valor esté disponible y el otro parámetro es el código ejecutable que debe ejecutarse en caso de que el El valor no está disponible. En aras de una mejor legibilidad, puede usar curring para dividir la función de dos parámetros en dos funciones de un parámetro cada uno. Esto es lo que básicamente hice aquí.
Sugerencia: Opt también proporciona el otro caso de uso donde desea ejecutar un fragmento de código en caso de que el valor no esté disponible. Esto podría hacerse también a través de Optional.filter.stuff, pero me pareció mucho más legible.
¡Espero que ayude!
Buena programación :-)
fuente
En caso de que desee almacenar el valor:
fuente
Supongamos que tiene una lista y evita el
isPresent()
problema (relacionado con las opciones) que podría usar.iterator().hasNext()
para verificar si no está presente.fuente