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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 23:05:18  来源:igfitidea点击:

findAny orElse after filter

javajava-8java-streamoptional

提问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 orElseargument. That's why orElseGetexists: 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 expressionbefore invoking the method orElseand 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 StreamAPI. If you want to evaluate a single item, you don't need to create a single-element stream just to call findAnyafterwards. You can create an Optionalin the first place:

但是,这是对StreamAPI的不必要使用。如果要评估单个项目,则无需创建单元素流以供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