2017-02-23 29 views
1

在Java 8流过滤器,是有办法适用于基于条件的流过滤器,的Java 8应用基于条件

例如

我有这样的流

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()); 
} 

我加入滤波器

.filter(K - > isAccessDisplayEnabled((源)K)))

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

请让我知道

回答

7

一种方式来做到这一点是

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()); 

另一

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

在任何情况下,请注意如何在开始执行一个类型转换,简化了整个流pipline。

这两种解决方案都避免为每个流元素重新计算isAccessDisplayEnabled,然而,第二种解决方案依赖于JVM在内存中嵌入s -> true的能力,此代码对性能至关重要。

+0

我无法理解这一行,isAccessDisplayEnabled? s - > true:s - > isAccessDisplayEnabled(s),请你多解释一下,或者写一个解释它的博客。 – Umar

+0

尝试读取它为'isAccessDisplayEnabled? (s - > true):(s - > isAccessDisplayEnabled(s))'。如果'isAccessDisplayEnabled'为'true',则使用lambda表达式's - > true',这实际上就像没有过滤器一样,否则使用's - > isAccessDisplayEnabled(s)'。它是[ternary operator](https://docs.oracle.com/javase/tutorial/java/nutsandbolts/op2.html)与两个可选的[lambda表达式](http://docs.oracle.com/)的组合JavaSE的/教程/ JAVA/javaOO/lambdaexpressions.html)。 – Holger

+0

@霍尔德:好的三元,但顺序是错的,不是吗?我猜如果你有一个布尔isAccessDisplayEnabled,那么你想过滤,否则如果为false,你不过滤。 'isAccessDisplayEnabled? (s - > isAccessDisplayEnabled(s)):(s - > true)' – sandwood

2

您的情况与您的方法具有相同的名称。我要去承担你的意思是对于那些有所不同,所以让我们说这是这样的:

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/else,可以改为在第一过滤器进行检查:

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

在其他情况下,你把一切并删除isAccessDisplayEnabled()方法调用,这样的条件实际上是“如果someCondition是假的或isAccessDisplayEnabled(K)”。如果someCondition输出为false,则会跳过isAccessDisplayEnabled()检查。

+2

......但'someCondition'可能会重新评估每个元素。 – Holger

+2

变量和方法在Java中可以具有相同的名称。在这个意义上,Java是一个Lisp 2。 ;) –

+0

@DavidConrad我相信这是真的,但我不认为他是这个意思。我只是改变了变量名来清除事情。 – jchitel