sirve settitle que para java java-8 optional

java - settitle - ¿Cuál es la forma más elegante de combinar los opcionales?



para que sirve settitle en java (7)

Esto es lo que tengo hasta ahora:

Optional<Foo> firstChoice = firstChoice(); Optional<Foo> secondChoice = secondChoice(); return Optional.ofNullable(firstChoice.orElse(secondChoice.orElse(null)));

Esto me parece a la vez horrible y derrochador. Si firstChoice está presente, estoy calculando innecesariamente secondChoice.

También hay una versión más eficiente:

Optional<Foo> firstChoice = firstChoice(); if(firstChoice.isPresent()) { return firstChoice; } else { return secondChoice(); }

Aquí no puedo encadenar alguna función de mapeo al final sin duplicar el mapeador o declarar otra variable local. Todo esto hace que el código sea más complicado que el problema real que se está resolviendo.

Prefiero estar escribiendo esto:

return firstChoice().alternatively(secondChoice());

Sin embargo Opcional :: por supuesto, obviamente no existe. ¿Ahora que?


Aquí está la generalización de la solución @marstran para cualquier número de opcionales:

@SafeVarargs public static <T> Optional<T> selectOptional(Supplier<Optional<T>>... optionals) { return Arrays.stream(optionals) .reduce((s1, s2) -> () -> s1.get().map(Optional::of).orElseGet(s2)) .orElse(Optional::empty).get(); }

Prueba:

public static Optional<String> first() { System.out.println("foo called"); return Optional.empty(); } public static Optional<String> second() { System.out.println("bar called"); return Optional.of("bar"); } public static Optional<String> third() { System.out.println("baz called"); return Optional.of("baz"); } public static void main(String[] args) { System.out.println(selectOptional(() -> first(), () -> second(), () -> third())); }

Salida:

foo called bar called Optional[bar]


Aquí hay una manera que funciona para un número arbitrario de Optional basados ​​en una API de flujo:

return Arrays.asList(firstChoice, secondChoice).stream() .filter(Optional::isPresent) .map(Optional::get) .findFirst().orElse(null);

No es el más corto. Pero más sencillo y comprensible.

Otra forma es usar firstNonNull() de Guava de commons-lang si ya está usando una de esas bibliotecas:

firstNonNull(firstChoice.orElse(null), secondChoice.orElse(null));


Cálculos perezosos y número arbitrario de elementos Optional

Stream.<Supplier<Optional<Foo>>>of( this::firstChoice, this::secondChoice ).map( Supplier::get ).filter( Optional::isPresent ).findFirst( ).orElseGet( Optional::empty );


Estaba lo suficientemente frustrado por el hecho de que esto no estaba soportado en Java 8, que volví a los opcionales de guava que tienen or :

public abstract Optional<T> or(Optional<? extends T> secondChoice)

Devuelve este opcional si tiene un valor presente; segunda elección en caso contrario.


Prueba esto:

firstChoice().map(Optional::of) .orElseGet(this::secondChoice);

El método de mapa te da un Optional<Optional<Foo>> . Luego, el método orElseGet aplana esto de nuevo a un Optional<Foo> . El método firstChoice() solo se evaluará si firstChoice() devuelve el opcional vacío.


Tal vez algo como esto:

Optional<String> finalChoice = Optional.ofNullable(firstChoice() .orElseGet(() -> secondChoice() .orElseGet(() -> null)));

Desde: Chaining Optionals en Java 8


Usted simplemente puede reemplazar eso con,

Optional<Foo> firstChoice = firstChoice(); return firstChoice.isPresent()? firstChoice : secondChoice();

El código anterior no llamará a menos que firstChoice.isPresent () sea ​​falso.

Pero tienes que estar preparado para llamar a ambas funciones para obtener la salida deseada. No hay otra manera de escapar de la comprobación.

  • El mejor de los casos es la primera opción, volviendo verdad.
  • El peor de los casos será la primera opción devolviendo falso, por lo tanto, otro método requiere una segunda opción