Estoy tratando de entender la diferencia entre los métodos Optional<T>.orElse()
y Optional<T>.orElseGet()
.
La descripción del orElse()
método es "Devuelve el valor si está presente, de lo contrario devuelve otro".
Mientras que la descripción del orElseGet()
método es "Devuelve el valor si está presente, de lo contrario invoca a otro y devuelve el resultado de esa invocación".
El orElseGet()
método toma una interfaz funcional de proveedor, que esencialmente no toma ningún parámetro y devuelve T
.
¿En qué situación necesitarías usar orElseGet()
? Si tienes un método, T myDefault()
¿por qué no lo harías en optional.orElse(myDefault())
lugar de hacerlo optional.orElseGet(() -> myDefault())
?
No parece que orElseGet()
posponga la ejecución de la expresión lambda en algún momento posterior o algo así, entonces, ¿qué sentido tiene? (Pensé que sería más útil si devolviera un dispositivo más seguro Optional<T>
que get()
nunca arroja un NoSuchElementException
y isPresent()
siempre devuelve verdadero ... pero evidentemente no lo es, simplemente regresa T
como orElse()
).
¿Hay alguna otra diferencia que me estoy perdiendo?
orElseGet
, llama al proveedor solo si no hay valor.orElse()
lamyDefault()
método todavía se llama, pero su valor de retorno no se utiliza.orElseGet()
puede dar lugar a algunos errores graves: medium.com/alphadev-thoughts/…Respuestas:
Tome estos dos escenarios:
Si
opt
no contiene un valor, los dos son equivalentes. Pero siopt
no contener un valor, ¿cuántosFoo
objetos serán creados?Ps: por supuesto, en este ejemplo, la diferencia probablemente no sería medible, pero si tiene que obtener su valor predeterminado de un servicio web remoto, por ejemplo, o de una base de datos, de repente se vuelve muy importante.
fuente
Foo
objeto, mientras que en el primer caso se creará, pero no lo use si hay un valor dentro de laOptional
.System.out.println()
es un cálculo sino una declaración que produce un efecto secundario observable. Y ya dije que los efectos secundarios observables dificultarán las optimizaciones (el flujo de salida de la consola es un recurso externo).Respuesta corta:
Optional.isPresent()
valorOptional.isPresent() == false
En el código real, es posible que desee considerar el segundo enfoque cuando el recurso requerido es costoso de obtener .
Para más detalles, considere el siguiente ejemplo con esta función:
La diferencia es la siguiente:
Cuando
optional.isPresent() == false
, no hay diferencia entre dos formas. Sin embargo, cuandooptional.isPresent() == true
,orElse()
siempre llama a la función posterior, lo desee o no.Finalmente, el caso de prueba utilizado es el siguiente:
Resultado:
Código:
fuente
Optional.isPresent() == false
en su lugar (falso, no cierto)Optional.orElse
qué estadosIf a value is present, returns the value, otherwise returns other
pueden implicar este comportamiento ...orElse()
se comporta similar a lafinally
detry-catch
expresión. ¿Estoy en lo correcto?Llegué aquí por el problema que Kudo mencionó.
Estoy compartiendo mi experiencia por los demás.
orElse
oorElseGet
esa es la pregunta:huellas dactilares
orElse
evalúa el valor de B () de manera interdependiente del valor de lo opcional. Por lo tanto,orElseGet
es vago.fuente
B()
a un método llamadoorElse()
oabc()
no hace ninguna diferencia,B()
se evalúa.or
prefijo engaña a los desarrolladores (incluyéndome a mí mismo cuando le pregunté el problema) para pensar que es una operación de cortocircuito, porque eso es a lo que estamos acostumbrados en condiciones booleanas. Sin embargo, no lo es, es solo un nombre de método que tieneor
en su prefijo, por lo que sus argumentos serán evaluados, independientemente de siOptional
lleva un valor o no. Es lamentable que la denominación sea confusa, no que podamos hacer nada al respecto.Yo diría que la mayor diferencia entre
orElse
yorElseGet
viene cuando queremos evaluar algo para obtener el nuevo valor en laelse
condición.Considere este simple ejemplo:
Ahora transformemos el ejemplo anterior para usar
Optional
junto conorElse
,Ahora transformemos el ejemplo anterior para usar
Optional
junto conorElseGet
,Cuando
orElse
se invoca,apicall().value
se evalúa y se pasa al método. Mientras que, en el caso deorElseGet
la evaluación solo ocurre si eloldValue
está vacío.orElseGet
permite una evaluación perezosa.fuente
El siguiente ejemplo debería demostrar la diferencia:
La respuesta también aparece en los documentos.
public T orElseGet(Supplier<? extends T> other)
:El
Supplier
no va a ser invocada si losOptional
presentes. mientras,public T orElse(T other)
:Si
other
es un método que devuelve una cadena, se invocará, pero su valor no se devolverá en caso de queOptional
exista.fuente
La diferencia es bastante sutil y si no prestas mucha atención, la seguirás usando de manera incorrecta.
La mejor manera de entender la diferencia entre
orElse()
yorElseGet()
es queorElse()
siempre se ejecutará siOptional<T>
es nulo o no , peroorElseGet()
solo se ejecutará cuandoOptional<T>
sea nulo .El significado del diccionario de orElse es : - ejecuta la parte cuando algo no está presente, pero aquí contradice, mira el siguiente ejemplo:
Puntos de referencia :
Espero que aclare las dudas de personas como yo que quieren el ejemplo básico básico :)
fuente
Antes que nada, verifique la declaración de ambos métodos.
1) OrElse: ejecuta la lógica y pasa el resultado como argumento.
2) OrElseGet: ejecuta la lógica si el valor dentro del opcional es nulo
Alguna explicación sobre la declaración anterior: El argumento de "Opcional.o Else" siempre se ejecuta independientemente del valor del objeto en opcional (nulo, vacío o con valor). Siempre tenga en cuenta el punto mencionado anteriormente al usar "Opcional.o Else", de lo contrario, el uso de "Opcional.o Else" puede ser muy arriesgado en la siguiente situación.
Riesgo-1) Problema de registro: si el contenido dentro o Else contiene alguna declaración de registro: en este caso, terminará registrándolo cada vez.
Riesgo-2) Problema de rendimiento: si el contenido interno o Else requiere mucho tiempo: el contenido intensivo de tiempo puede ser cualquier llamada de DB de operaciones de E / S, llamada de API, lectura de archivos. Si ponemos dicho contenido en orElse (), el sistema terminará ejecutando un código inútil.
Riesgo-3) Estado ilegal o problema de error: si el contenido dentro o Else está mutando algún estado de objeto: podríamos estar usando el mismo objeto en otro lugar, digamos dentro de la función Opcional.map y nos puede poner en un error crítico.
Entonces, ¿cuándo podemos ir con orElse ()? Prefiere usar orElse cuando el valor predeterminado es algún objeto constante, enum. En todos los casos anteriores, podemos ir con Opcional.orElseGet () (que solo se ejecuta cuando Opcional contiene un valor no vacío) en lugar de Opcional.orElse (). ¿¿Por qué?? En orElse, pasamos el valor de resultado predeterminado, pero en orElseGet pasamos el Proveedor y el método del Proveedor solo se ejecuta si el valor en Opcional es nulo.
Conclusiones clave de esto:
He explicado esto en el punto 2 ( "Opcional.map/Optional.orElse"! = "If / else" ) mi blog medio. Use Java8 como programador, no como codificador
fuente
Teniendo en cuenta el siguiente código:
si conseguimos
value
de esta manera:Optional.<String>ofNullable(null)
, no hay ninguna diferencia entre orElseGet () y OrElse (), pero si conseguimosvalue
de esta manera:Optional.<String>ofNullable("test")
,orelesMethod()
enorElseGet()
que no sea igualada, pero en laorElse()
que se llamaráfuente