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 NoSuchElementExceptiony isPresent()siempre devuelve verdadero ... pero evidentemente no lo es, simplemente regresa Tcomo 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
optno contiene un valor, los dos son equivalentes. Pero sioptno contener un valor, ¿cuántosFooobjetos 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
Fooobjeto, 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() == falseEn 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() == falseen su lugar (falso, no cierto)Optional.orElsequé estadosIf a value is present, returns the value, otherwise returns otherpueden implicar este comportamiento ...orElse()se comporta similar a lafinallydetry-catchexpresión. ¿Estoy en lo correcto?Llegué aquí por el problema que Kudo mencionó.
Estoy compartiendo mi experiencia por los demás.
orElseoorElseGetesa es la pregunta:huellas dactilares
orElseevalúa el valor de B () de manera interdependiente del valor de lo opcional. Por lo tanto,orElseGetes vago.fuente
B()a un método llamadoorElse()oabc()no hace ninguna diferencia,B()se evalúa.orprefijo 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 tieneoren su prefijo, por lo que sus argumentos serán evaluados, independientemente de siOptionallleva 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
orElseyorElseGetviene cuando queremos evaluar algo para obtener el nuevo valor en laelsecondición.Considere este simple ejemplo:
Ahora transformemos el ejemplo anterior para usar
Optionaljunto conorElse,Ahora transformemos el ejemplo anterior para usar
Optionaljunto conorElseGet,Cuando
orElsese invoca,apicall().valuese evalúa y se pasa al método. Mientras que, en el caso deorElseGetla evaluación solo ocurre si eloldValueestá vacío.orElseGetpermite 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
Supplierno va a ser invocada si losOptionalpresentes. mientras,public T orElse(T other):Si
otheres un método que devuelve una cadena, se invocará, pero su valor no se devolverá en caso de queOptionalexista.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
valuede esta manera:Optional.<String>ofNullable(null), no hay ninguna diferencia entre orElseGet () y OrElse (), pero si conseguimosvaluede esta manera:Optional.<String>ofNullable("test"),orelesMethod()enorElseGet()que no sea igualada, pero en laorElse()que se llamaráfuente