java findAny orElse 过滤后
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34588180/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
findAny orElse after filter
提问by paul
I'm using Stream filter findAny.orElse
, but it's not working as I expect, so I presume I'm not understanding how really works.
Here my code
我正在使用 Stream filter findAny.orElse
,但它并没有像我预期的那样工作,所以我想我不了解真正的工作原理。这是我的代码
return Stream.of(getObjectAttributeValue(product, matchCriteria.getFieldName()))
.map(o -> isIngredientRestricted(matchCriteria, (List<String>) o))
.filter(Boolean::valueOf)
.findAny().orElse(isCommercialHierarchyInfoRestricted(product, matchCriteria));
Basically what I was expecting was that if the first map emit a Boolean false, then it will be filter so then the findAny would not find any optional, so the orElse would be invoked. But even having a true in the filter the isCommercialHierarchyInfoRestricted is invoked.
基本上我期望的是,如果第一个映射发出布尔值 false,那么它将被过滤,因此 findAny 将找不到任何可选,因此将调用 orElse。但即使在过滤器中有一个 true ,也会调用 isCommercialHierarchyInfoRestricted 。
Any idea what I'm doing wrong?
知道我做错了什么吗?
回答by Tagir Valeev
You actually need to use orElseGet
:
你实际上需要使用orElseGet
:
.findAny().orElseGet(() -> isCommercialHierarchyInfoRestricted(product, matchCriteria));
In Java method argument is always evaluated prior to method call even if it's unnecessary inside the method, so you cannot avoid evaluating the orElse
argument. That's why orElseGet
exists: its argument is the function and the function can be not executed at all when it's not necessary.
在 Java 中,方法参数总是在方法调用之前进行评估,即使它在方法内部是不必要的,因此您无法避免评估orElse
参数。这就是orElseGet
存在的原因:它的参数是函数,并且函数在不需要时根本不能执行。
回答by Holger
As Tagir explained, using orElse(expression)
always causes the evaluation of expression
before invoking the method orElse
and you have to use orElseGet(() -> expression)
instead to defer the evaluation of the expression.
正如Tagir 解释的那样, usingorElse(expression)
总是会导致expression
在调用方法之前评估 ,orElse
而您必须改为使用orElseGet(() -> expression)
来推迟表达式的评估。
However, this is an unnecessary use of the Stream
API. If you want to evaluate a single item, you don't need to create a single-element stream just to call findAny
afterwards. You can create an Optional
in the first place:
但是,这是对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));
However, even that is an unnecessary complication compared to the equivalent ordinary Java language construct:
然而,与等效的普通 Java 语言结构相比,即使这样也是不必要的复杂化:
return isIngredientRestricted(matchCriteria,
(List<String>)getObjectAttributeValue(product, matchCriteria.getFieldName()))
|| isCommercialHierarchyInfoRestricted(product, matchCriteria);
This does exactly the same without the need for additional APIs nor lambda expressions. The ||
operator also guarantees that the second expression won't get evaluated, if the first one evaluates to true
.
这完全相同,无需额外的 API 或 lambda 表达式。该||
运营商还保证了第二个表达式将不会得到评估,如果第一个计算结果为true
。