我正在使用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
,则不会对第二个表达式进行计算。