Java 8 Streams: filter and predicate negation
Recently there was an interesting discussion on the use of predicate negation in the .filter method on a stream by members of the LJC mailing list, so I thought it would be worth summarising it in a blog post. The discussion was about ways to use .filter and to negate the predicate.
- Code for this post is available in my github account.
This is perhaps how you might think about doing, but here are some alternative ways.
Stream.of(1, 2, 3, 4, 5, 6, 7) .filter(((Predicate) c -> c % 2 == 0).negate())
Answer 1: Write a predicate utility method
You can simplify this by writing a utility method that performs the negation.
public static <R> Predicate<R> not(Predicate<R> predicate) { return predicate.negate(); }
Which results in much neater code.
Stream.of(1, 2, 3, 4, 5, 6, 7) .filter(not(c -> c % 2 == 0))
Answer 2: Use an identity function to convert the method reference to a Predicate
We use a utility method to convert a method reference to a predicate.
public static <T> Predicate<T> predicate(Predicate<T> predicate) { return predicate; }
although the code is not as neat.
Stream.of("Cat", "", "Dog") .filter(predicate(String::isEmpty).negate())
- References: Heinz’s Lambda Reduction Principle
Answer 3: Use the not (!) operator
Use the familiar not operator.
Stream.of(1, 2, 3, 4, 5, 6, 7) .filter((c -> c % 2 != 0)) Stream.of("Cat", "", "Dog") .filter(str -> !str.isEmpty())
The code is much simpler and immediately familiar.
It is argued that method references are often harder to read and are trickier when refactoring than simple lambdas and that that mixing lambdas and method references in a Stream chain is confusing to the reader. Reference: Java SE 8 Best Practices
When you use a method reference and want the IDE to create the method, IntelliJ creates this as a static method with the object as the first argument. Using the not operator avoids this.
Here are some useful references:
- Java 8 Lambdas: Functional Programming For The Masses
- Java SE 8 Best Practices
- Heinz’s Lambda Reduction Principle
- LJC mailing list
- Method references have a bug in some JDK versions
Reference: | Java 8 Streams: filter and predicate negation from our JCG partner Alex Theedom at the alex.theedom blog. |