我正在使用Stream过滤器findAny.orElse,但是它没有按我预期的那样工作,所以我想我不了解它的实际工作原理。
这是我的代码

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

基本上,我期望的是,如果第一个映射发出 boolean 值false,则将对其进行过滤,因此findAny将找不到任何 optional 内容,因此将调用orElse。但是,即使在筛选器中为true,也会调用isCommercialHierarchyInfoRestricted。

知道我在做什么错吗?

最佳答案

Tagir explained一样,使用orElse(expression)总是会导致在调用方法expression之前对orElse求值,而您必须使用orElseGet(() -> 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,则不会对第二个表达式进行计算。

10-02 22:01