【问题标题】:Returning from Java Optional ifPresent()从 Java 中返回可选 ifPresent()
【发布时间】:2019-07-19 13:23:15
【问题描述】:

我了解您无法从 ifPresent() 返回,因此此示例不起作用:

public boolean checkSomethingIfPresent() {
    mightReturnAString().ifPresent((item) -> {
        if (item.equals("something")) {
            // Do some other stuff like use "something" in API calls
            return true; // Does not compile
        }
    });
    return false;
}

mightReturnAString()可以返回一个有效的字符串或一个空的可选值。我所做的工作是:

public boolean checkSomethingIsPresent() {
    Optional<String> result = mightReturnAString();

    if (result.isPresent()) {
        String item = result.get();
        if (item.equals("something") {
            // Do some other stuff like use "something" in API calls
            return true;
        }
    }
    return false;
}

这更长,并且与首先检查空值没有太大区别。我觉得使用 Optional 一定有更简洁的方式。

【问题讨论】:

  • 使用map:return mightReturnAsString().map("something"::equals);
  • 你为什么不只使用谓词?
  • 欢迎发布示例或指向现有问题的链接,以说明您的意思。

标签: java java-8 optional


【解决方案1】:

顺便说一句,如果你真的想从 Optional 中获得价值,请使用:

Optional<User> user = service.getCurrentUset();

return user.map(User::getId);

【讨论】:

    【解决方案2】:

    理想的解决方案是“命令-查询分离”:创建一个方法(命令)来处理字符串(如果存在)。还有另一种方法(查询)告诉你它是否存在。

    但是,我们生活的世界并不理想,完美的解决方案永远不可能。如果在您的情况下您无法将命令和查询分开,我的口味是 shmosel 已经提出的想法:映射到 boolean。作为细节,我会使用filter 而不是内部的if 声明:

    public boolean checkSomethingIfPresent() {
        return mightReturnAString().filter(item -> item.equals("something"))
                .map(item -> {
                    // Do some other stuff like use "something" in API calls
                    return true; // (compiles)
                })
                .orElse(false);
    }
    

    我不喜欢它的调用链有副作用,除了ifPresentifPresentOrElse(当然还有orElseThrow),通常不会出现这种情况。

    如果我们坚持使用ifPresent 让副作用更清晰,那是可能的:

        AtomicBoolean result = new AtomicBoolean(false);
        mightReturnAString().filter(item -> item.equals("something"))
                .ifPresent(item -> {
                    // Do some other stuff like use "something" in API calls
                    result.set(true);
                });
        return result.get();
    

    我使用AtomicBoolean 作为结果的容器,因为我们不允许从 lambda 中分配给原始 boolean。我们不需要它的原子性,但它也无害。

    链接: 维基百科上的Command–query separation

    【讨论】:

      【解决方案3】:

      虽然@nullpointer 和@Ravindra 展示了如何将 Optional 与另一个条件合并,但您必须做更多工作才能调用 API 并按照您在问题中提出的要求执行其他操作。在我看来,以下内容看起来非常可读和简洁:

      private static boolean checkSomethingIfPresent() {
          Optional<String> str = mightReturnAString();
          if (str.filter(s -> s.equals("something")).isPresent()) {
              //call APIs here using str.get()
              return true;
          }
          return false;
      }
      

      更好的设计是链接方法:

      private static void checkSomethingIfPresent() {
          mightReturnFilteredString().ifPresent(s -> {
              //call APIs here
          });
      }
      
      private static Optional<String> mightReturnFilteredString() {
          return mightReturnAString().filter(s -> s.equals("something"));
      }
      
      private static Optional<String> mightReturnAString() {
          return Optional.of("something");
      }
      

      【讨论】:

        【解决方案4】:

        我认为您正在寻找的只是filter 然后检查是否存在:

        return result.filter(a -> a.equals("something")).isPresent();
        

        【讨论】:

        • 你的答案和@ravindra-ranwala 的答案似乎都有效——不确定哪个最适合这个用例。
        • @FredClausen 它们可以工作,但你可以使用这些“API 调用等其他事情”吗?
        • @FredClausen 好吧,如果你只想检查一个条件,filterPredicate 会更合适,因为另一方面,map 应该是理想的,当你正在转换目的。毕竟map 带有谓词只会产生Boolean
        • 啊,是的,在我需要它们的完整项目中尝试这些建议。将基于此更新。
        • 你也可以使用"something"::equals来代替a -&gt; a.equals("something")。我不会把“其他东西”放在这里,因为你仍然可以将它作为一个独立的操作链接起来,或者当这个检查返回 true 时执行它。在后一种情况下,将无法访问该值,但当该值被证明为 "something" 时,您无论如何都不需要它。
        【解决方案5】:

        映射到布尔值怎么样?

        public boolean checkSomethingIfPresent() {
            return mightReturnAString().map(item -> {
                if (item.equals("something")) {
                    // Do some other stuff like use "something" in API calls
                    return true; // Does not compile
                }
                return false; // or null
            }).orElse(false);
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-10-20
          • 2017-09-08
          • 2018-01-03
          相关资源
          最近更新 更多