Four Ways to Negate a Predicate in the Steam API's Filter Method
In Java there are various ways to negate a predicate in the Stream API's filter method. In this post I present four approaches.
Join the DZone community and get the full member experience.
Join For FreeThere are various ways to negate the predicate passed to the filter method of the Stream API. In this blog post, I present four ways to code this negation.
1. Use the Negate Method of the Predicate API
The first approach is to take advantage of the Predicate API's negate() method. This is perhaps how you might have thought about doing it first off and would look something like the following:
xxxxxxxxxx
Stream.of(1, 2, 3, 4, 5, 6, 7).filter(((Predicate) c -> c % 2 == 0).negate());
but here are some alternative approaches.
2. Write a Predicate Utility Method
You can simplify this approach by writing a utility method that is capable of performing the negation.
xxxxxxxxxx
public static <R> Predicate<R> not(Predicate<R> predicate) {
return predicate.negate();
}
Which results in much neater code.
xxxxxxxxxx
Stream.of(1, 2, 3, 4, 5, 6, 7).filter(not(c -> c % 2 == 0));
The utility method can of course be reused throughout the application.
3. Use an Identity Function to Convert the Method Reference to a Predicate
With this approach you use a utility method to convert a method reference to a predicate.
xxxxxxxxxx
public static <T> Predicate<T> predicate(Predicate<T> predicate) {
return predicate;
}
although the code is not as neat.
xxxxxxxxxx
Stream.of("Cat", "", "Dog").filter(predicate(String::isEmpty).negate());
References: Heinz’s Lambda Reduction Principle
4. Use the Not (!) Operator
Finally you can use the familiar, not
operator.
xxxxxxxxxx
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.
Conclusion
It is argued that method references are often harder to read and are trickier when refactoring than simple lambdas and that mixing lambdas and method references in a Stream
chain is confusing to the reader.
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.
Published at DZone with permission of Alex Theedom, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments