Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 Applying stream filter based on a condition

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

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.

Please let me know

like image 836
Umar Avatar asked Feb 23 '17 19:02

Umar


People also ask

How do you add two conditions to a stream filter?

You can use the firstPredicate. and(secondPredicate) to filter results on multiple conditions. The first predicate receives each element from the stream. If the first predicate evaluates to true, then te second predicate receives the same element.

How do you filter a list of objects using a stream?

Java stream provides a method filter() to filter stream elements on the basis of given predicate. Suppose you want to get only even elements of your list then you can do this easily with the help of filter method. This method takes predicate as an argument and returns a stream of consisting of resulted elements.

What is the purpose of filter method of stream in Java 8?

The filter() function of the Java stream allows you to narrow down the stream's items based on a criterion. If you only want items that are even on your list, you can use the filter method to do this. This method accepts a predicate as an input and returns a list of elements that are the results of that predicate.

Can we use multiple filter in Java 8?

Overview However, we'll learn how to use the filter() method with as many condition filters as we require. More filters can be applied in a variety of methods, such using the filter() method twice or supplying another predicate to the Predicate. and() method.


2 Answers

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 isAccessDisplayEnabled for every stream element, however, the second relies on the JVM’s capability of inlining s -> true when this code turns out to be performance critical.

like image 162
Holger Avatar answered Oct 06 '22 12:10

Holger


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:

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.

like image 28
jchitel Avatar answered Oct 06 '22 12:10

jchitel