【问题标题】:Combine Java 8 Optionals with conditional AND将 Java 8 Optionals 与条件 AND 结合使用
【发布时间】:2016-09-23 08:45:36
【问题描述】:

我的问题是我有两个或多个 Optionals 包装不同的类型。 我想执行一个只有在所有选项都不为空时才能执行的操作。

目前我是这样做的:

    Optional<PatientCase> caseOptional = patientCaseRepository.findOneById(caseId);
    Optional<User> userOptional = userRepository.findOneById(caseId);

    if(userOptional.isPresent() && caseOptional.isPresent()) {
        caseOptional.get().getProcess().setDesigner(userOptional.get());
    }

在我看来,if 条件感觉不对。 我知道可以使用 orElse 链接 Optionals。 但就我而言,我不想要一个合乎逻辑的Else。 有没有办法创建 AND 运算符来组合两个或多个 Optional 类似于这个伪代码?

caseOptional.and.userOptional.ifPresent((theCase,user) -> //Perform Stuff);

【问题讨论】:

    标签: java java-8 java-stream optional logical-operators


    【解决方案1】:

    有一个逻辑 AND 操作,但没有(简单的)方法将其转换为二值 Optional,换句话说,这(再次)受到缺少对或元组类型的影响。例如

    caseOptional.flatMap(theCase -> userOptional
            .map(user -> new AbstractMap.SimpleEntry<>(theCase, user)))
        .ifPresent(e -> e.getKey().getProcess().setDesigner(e.getValue()));
    

    它使用AbstractMap.SimpleEntry 作为不存在的元组类型的替代。

    另一种方法是使用单例映射作为对:

    caseOptional.flatMap(theCase -> userOptional
            .map(user -> Collections.singletonMap(theCase, user)))
        .ifPresent(m -> m.forEach((c, u) -> c.getProcess().setDesigner(u)));
    

    但在这种特定情况下,您可以使用更简单的

    caseOptional.map(PatientCase::getProcess)
                .ifPresent(p -> userOptional.ifPresent(p::setDesigner));
    

    caseOptional.ifPresent(c -> userOptional.ifPresent(u -> c.getProcess().setDesigner(u)));
    

    改为。

    【讨论】:

    • 最后一个形式看起来很像一个monad,也许可以形式化为一个:)
    • 感谢给定的示例/建议。前两个似乎只适用于两个,并且不超过两个可选。我认为使用包含选项的自定义对象可以实现更多。但这是一个更大的开销。最后两个建议表明可以使用 ifPresent 以嵌套方式链接多个选项。所以它是给定问题的解决方案,但不幸的是,代码的可读性随着每个添加的可选选项而降低。如果有人找到另一种可读性更好的方法,我仍然会稍等,否则我会接受这个作为答案。
    【解决方案2】:

    没有直接的方法。

    Stram allMatch 将像 ifPresent 一样用于许多选项:

    Stream.of(optional1, optional2, ...).allMatch(Optional::isPresent)
    

    【讨论】:

    • 使用这种技术,我可以验证所有选项都存在。但是不可能链接更多的函数调用。这一步必须再次使用 if 子句来控制,稍后我必须解开这些选项。但是在验证两个以上的选项时,编码开销会小一些,所以它的方向是正确的。
    【解决方案3】:

    我知道问题本身已经得到解答,但一般来说,可选1(称为'A')和可选2(称为'B')组合的所有状态都可以通过链接@获得987654323@ 和 orElse() 或类似名称。这类问题的关键是要记住,Optional.map() 中应用的函数仅适用于“真实”值。

    A.map(a->B.map(b->"A&&B").
               orElse("A&&!B")).
      orElse(B.map(b->"!A&&B").
               orElse("!A&&!B"));
    

    所以map() 处理 Optional 不为空的情况,orElse() 处理 Optional 为空的情况。

    【讨论】:

      猜你喜欢
      • 2015-02-14
      • 1970-01-01
      • 1970-01-01
      • 2017-02-02
      • 2017-03-28
      • 2020-02-14
      • 1970-01-01
      • 1970-01-01
      • 2013-10-09
      相关资源
      最近更新 更多