Каково предполагаемое поведение Guava в Optional.or ()? - PullRequest
2 голосов
/ 06 марта 2019

Метод, в котором я соединяю опции, ведет себя не так, как я думал при чтении документов.

Предположим, все function_n вернуть Optional<Foo>

public Foo getFooFromService() {
     return this.function_1()
         .or(this.function_2())
         .or(this.function_3())
         .or(DEFAULT_VAL)

Я думал, что для приведенного выше кода, если function_1 вернет необязательный Optional, тогда программа вернет его внутреннее значение (результат .get ()) и не будет выполнять никаких дальнейших вычислений на * 1011. * и function_3

Моя программа наверняка выполняет дополнительные вычисления

Ответы [ 2 ]

5 голосов
/ 06 марта 2019

Чтобы вернуть значение из getFooFromService, необходимо выполнить function_1 и три or с, что означает, что их параметры будут оценены. function_2 и function_3 будут выполняться при любых обстоятельствах.

Опция, которая может подойти вам, - это перегруженная версия, которая принимает Supplier, что подразумевает ленивую оценку.

public abstract T or(Supplier<? extends T> supplier)

UPDATE

Это @Beta метод (подлежит изменению), и я считаю его совершенно бесполезным. Это разрешает от Supplier<? extend T> до T, таким образом, разрушает возможность построения цепочки. По сути, вы не можете переписать свой фрагмент, чтобы использовать этот метод.

ОБНОВЛЕНИЕ 1

Но вы можете переключиться на Java Optional и написать

return function_1()
       .orElseGet(() -> function_2()
                        .orElseGet(() -> function_3()
                                         .orElse(DEFAULT_VAL)));

, который не так выразителен, но работает, как ожидалось.

Мое форматирование ужасно, но вы поняли;)

1 голос
/ 06 марта 2019

Гуава "мягко рекомендует" использовать Java Optional

Поэтому используйте Java Optional для написания довольно разборчивого кода:

import java.util.*;
class Main {
  public static void main(String[] args) {
    new Main().getFooFromService();
  }
  String getFooFromService() {
    return this.function_1()
      .or(this::function_2) // Requires Java 9
      .or(this::function_3) // Requires Java 9
      .orElse("DEFAULT_VALUE");
  }

  Optional<String> function_1() {
    System.out.println("function_1 called");
    return Optional.empty();
  }

  Optional<String> function_2() {
    System.out.println("function_2 called");
    return Optional.of("b");
  }

  Optional<String> function_3() {
    System.out.println("function_3 called");
    return Optional.of("c");
  }
}

Вы увидите, что в этом случае при заданной настройке вызываются function_1 и function_2, но не function_3.

...