【问题标题】:findAny orElse after filter过滤后查找任何或其他
【发布时间】:2016-04-07 21:22:06
【问题描述】:

我正在使用流过滤器findAny.orElse,但它没有按我预期的那样工作,所以我想我不明白它是如何工作的。 这是我的代码

return Stream.of(getObjectAttributeValue(product, matchCriteria.getFieldName()))
             .map(o -> isIngredientRestricted(matchCriteria, (List<String>) o))
             .filter(Boolean::valueOf)
             .findAny().orElse(isCommercialHierarchyInfoRestricted(product, matchCriteria));

基本上我所期望的是,如果第一个映射发出布尔值 false,那么它将是过滤器,因此 findAny 将找不到任何可选的,因此将调用 orElse。但即使在过滤器中有一个 true ,也会调用 isCommercialHierarchyInfoRestricted。

知道我做错了什么吗?

【问题讨论】:

  • orElse 被调用还是isCommercialHierarchyInfoRestricted 被调用?
  • .map(…).filter(Boolean::valueOf) 看起来很荒谬。为什么不首先使用.filter(…),即.filter(o -&gt; isIngredientRestricted(matchCriteria, (List&lt;String&gt;) o))
  • @zeroflagL isCommercialHierarchyInfoRestricted 被调用。也许这里的主要问题是我不应该使用 Stream
  • 哦,我明白了。您希望将 boolean 结果作为整体结果。

标签: java java-8 java-stream optional


【解决方案1】:

你实际上需要使用orElseGet:

.findAny().orElseGet(() -> isCommercialHierarchyInfoRestricted(product, matchCriteria));

在 Java 中,方法参数总是在方法调用之前进行评估,即使在方法中它是不必要的,所以你不能避免评估 orElse 参数。这就是orElseGet存在的原因:它的参数是函数,不需要的时候函数根本不执行。

【讨论】:

    【解决方案2】:

    作为Tagir explained,使用orElse(expression) 总是会在调用orElse 方法之前导致对expression 的评估,而您必须使用orElseGet(() -&gt; expression) 来推迟对表达式的评估。

    但是,这是对Stream API 的不必要使用。如果你想评估单个项目,你不需要创建一个单元素流只是为了在之后调用findAny。您可以首先创建一个Optional

    return Optional.of(getObjectAttributeValue(product, matchCriteria.getFieldName()))
         .map(o -> isIngredientRestricted(matchCriteria, (List<String>)o))
         .filter(b -> b)
         .orElseGet(() -> isCommercialHierarchyInfoRestricted(product, matchCriteria));
    

    但是,与等效的普通 Java 语言结构相比,即使这样也是不必要的复杂化:

    return isIngredientRestricted(matchCriteria,
               (List<String>)getObjectAttributeValue(product, matchCriteria.getFieldName()))
      ||  isCommercialHierarchyInfoRestricted(product, matchCriteria);
    

    这完全一样,无需额外的 API 或 lambda 表达式。 || 运算符还保证如果第一个表达式的计算结果为 true,则不会计算第二个表达式。

    【讨论】:

    • 是的,有时我们想要更多地使用函数式编程。我在不使用 Stream 的情况下像以前一样恢复。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-11
    • 2018-06-12
    • 1970-01-01
    相关资源
    最近更新 更多