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
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.
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With