Java 8 基于条件应用流过滤器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42424191/
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-08-12 00:08:32  来源:igfitidea点击:

Java 8 Applying stream filter based on a condition

javajava-8java-stream

提问by Umar

In Java 8, is there a way to apply the filter on a stream based on a condition,

在 Java 8 中,有没有办法根据条件在流上应用过滤器,

example

例子

I have this stream

我有这个流

if (isAccessDisplayEnabled) {
     src = (List < Source > ) sourceMeta.getAllSources.parallelStream()
         .filter(k - > isAccessDisplayEnabled((Source) k))
         .filter(k - > containsAll((Source) k, substrings, searchString))
         .collect(Collectors.toList());
 } else {
     src = (List < Source > ) sourceMeta.getAllSources.parallelStream()
         .filter(k - > containsAll((Source) k, substrings, searchString))
         .collect(Collectors.toList());
 }

I am adding the filter

我正在添加过滤器

.filter(k - > isAccessDisplayEnabled((Source) k)))

on the stream based on the if-else condition. Is there a way to avoid that if-else, since if there are more filters coming up,then it will be hard to maintain.

在基于 if-else 条件的流上。有没有办法避免if-else,因为如果有更多的过滤器出现,那么它将很难维护。

Please let me know

请告诉我

采纳答案by Holger

One way to do it is

一种方法是

Stream<Source> stream = sourceMeta.getAllSources.parallelStream().map(x -> (Source)x);
if(isAccessDisplayEnabled) stream = stream.filter(s -> isAccessDisplayEnabled(s));
src = stream.filter(s - > containsAll(s, substrings, searchString))
            .collect(Collectors.toList());

another

其他

 src = sourceMeta.getAllSources.parallelStream().map(x -> (Source)x)
     .filter(isAccessDisplayEnabled? s - > isAccessDisplayEnabled(s): s -> true)
     .filter(s - > containsAll(s, substrings, searchString))
     .collect(Collectors.toList());

In either case, note how performing one type cast at the beginning simplifies the entire stream pipline.

无论哪种情况,请注意在开始时执行一种类型转换如何简化整个流管道。

Both solutions avoid re-evaluating isAccessDisplayEnabledfor every stream element, however, the second relies on the JVM's capability of inlining s -> truewhen this code turns out to be performance critical.

两种解决方案都避免重新评估isAccessDisplayEnabled每个流元素,但是,s -> true当此代码被证明对性能至关重要时,第二种解决方案依赖于 JVM 的内联能力。

回答by jchitel

Your condition has the same name as your method. I'm going to assume you meant for those to be different, so let's say it was this:

您的条件与您的方法同名。我会假设你的意思是那些不同的,所以假设是这样的:

if (someCondition) {
    src = (List < Source > ) sourceMeta.getAllSources.parallelStream()
        .filter(k - > isAccessDisplayEnabled((Source) k))
        .filter(k - > containsAll((Source) k, substrings, searchString))
        .collect(Collectors.toList());
} else {
    src = (List < Source > ) sourceMeta.getAllSources.parallelStream()
        .filter(k - > containsAll((Source) k, substrings, searchString))
        .collect(Collectors.toList());
}

If you want to remove the if/else, you can instead perform the check in the first filter:

如果要删除 if/else,则可以改为在第一个过滤器中执行检查:

src = (List < Source > ) sourceMeta.getAllSources.parallelStream()
    .filter(k - > !someCondition || isAccessDisplayEnabled((Source) k))
    .filter(k - > containsAll((Source) k, substrings, searchString))
    .collect(Collectors.toList());

In the else case, you take everything and remove the isAccessDisplayEnabled() method call, so the condition is effectively "if someCondition is false or isAccessDisplayEnabled(k)". If someCondition comes out false, then the isAccessDisplayEnabled() check is skipped.

在 else 情况下,您将所有内容都删除并删除 isAccessDisplayEnabled() 方法调用,因此条件实际上是“如果 someCondition 为 false 或 isAccessDisplayEnabled(k)”。如果 someCondition 为 false,则跳过 isAccessDisplayEnabled() 检查。