【问题标题】:Return Optional as it is if the returned Optional has value, else call another function [duplicate]如果返回的 Optional 具有值,则返回 Optional,否则调用另一个函数 [重复]
【发布时间】:2019-06-12 13:23:03
【问题描述】:

我有两个返回 Optional 的方法 func1 和 func2。 如果 func1 返回的 Optional 有值,则返回 Optional,否则调用 func2 并返回其 Optional。 一种方法是使用if-else。

Optional<MyObject> opt1 = func1();
if (opt1.isPresent()) {
    return opt1;
}
return func2();

但是,我希望使用 Java 8 Optional 来实现它并避免使用if-else。

类似:

return Optional.of(obj1) 
        .flatMap_returnOptionalIfvaluePresent(func1)
        .orElseReturnOptionalFromThis(func2)

任何人都可以提出一个好的方法吗?

【问题讨论】:

  • 什么是func1 和func2?如果它们是方法,请重新格式化您的代码以使其有效。提供预期的输入和期望的输出。提供if-else 使问题更清晰。
  • 您为什么要避免使用清晰简单的if-else 以获取难以阅读的方式?
  • 这可能是一个好问题,但目前尚不清楚您想要什么。发布您使用 if-else 的代码,这样您想要实现的目标就显而易见了。
  • @Michael 我和你在一起,如果 OP 来解释更多,这可能是一个相当好的问题

标签: java java-8 optional flatmap


【解决方案1】:

编辑:or

Java 9 及更高版本提供了一个非常优雅的解决方案:

Optional<String> myFunc() {
    return func1().or(this::func2);
}

or(在 Java 9 中引入)完全符合您的要求:如果从 func1 返回的 Optional 具有值,则返回它(或等效的 Optional)。如果没有,则调用供应商(此处为func2())以获取Optional,然后返回。

Java 8

有几种方法。在 Java 8 中,我更喜欢从 Optionals 中取出 func1 和 func2 中的值:

Optional<String> myFunc() {
    String returnValue = func1().orElse(func2().orElse(null));
    return Optional.ofNullable(returnValue);
}

编辑 2: @Holger 在评论中的替代建议足以在答案中引用(Holger,您可能只是因为问题已关闭而将其作为评论发布,因此您不能发表你自己的答案):

    return func1().map(Optional::of).orElse(func2());

反之亦然:使用Optional::of 的映射将func1 中的Optional 包装在内部,而Optional 仅当它有一个值时,orElse 才会再次将其解包。

如果对func2 的调用很昂贵,您可能希望在不需要时避免调用(当func1 提供值时):

    String returnValue = func1().orElseGet(() -> func2().orElse(null));

或者在 Holger 的版本中:

    return func1().map(Optional::of).orElseGet(this::func2);

在其他几个答案中使用的isPresent 非常低级,我很少使用它,仅作为最后的手段。

【讨论】:

  • 有没有可选的API来消除return Optional.ofNullable(returnValue);
  • 不,@adimoh,但如果您愿意,当然可以内联它:return Optional.ofNullable(func1().orElse(func2().orElse(null)));。
  • 使用func1().orElseGet(() -&gt; func2().orElse(null)) 会带来轻微的改进,因为func2 不会被急切地执行。不过很好的解决方案。
  • 是的,@ernest_k,这正是我在答案底部附近所说的。英雄所见略同。 :-)
  • return func1().map(Optional::of).orElse(func2()); 或者,对于昂贵的func2 操作,return func1().map(Optional::of).orElseGet(this::func2);...
【解决方案2】:

如果你使用 java 9+,你可以使用Optional.or:

return func1().or(() -> func2());

在 Java 8 中,您可能需要从结果中创建一个新的 Optional(使用 orElseGet 以避免急切执行):

return Optional.ofNullable(func1().orElseGet(() -> func2().orElse(null)));

【讨论】:

    【解决方案3】:

    类似的东西呢

    Object value1 = func1();
    return value1.isPresent() ? value1 : func2();
    

    除非我误解了你的意思,否则如果它存在,它将从第一个函数返回值,如果它不存在,则调用 func2() 以返回第二个可选函数。您可能可以将其进一步简化为 func1().isPresent,但它使其不太清晰。

    【讨论】:

      【解决方案4】:

      如果我正确理解所有内容,它会是这样的:

      Optional.of(obj1)
              .filter(obj -> func1().isPresent())
              .orElse(func2());
      

      【讨论】:

      • orElse 返回 Optional 的值。我想返回 Optional 本身。
      • orElse 返回 func2() 函数的结果并返回 Optional,不是吗?
      【解决方案5】:

      这是一个更通用的版本,使用 n 函数:

      private static <T> Optional<T> firstPresent(Supplier<Optional<T>>... optionals) {
          return Stream.of(optionals)
                  .map(Supplier::get)
                  .filter(Optional::isPresent)
                  .findFirst()
                  .orElse(Optional.empty());
      }
      

      这样使用:

          Optional<String> result = firstPresent(() -> func1(null), () -> func2("abc"));
      

      【讨论】:

        猜你喜欢
        • 2021-10-09
        • 1970-01-01
        • 2022-01-06
        • 1970-01-01
        • 1970-01-01
        • 2018-04-10
        • 2019-07-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多