Predicate.not for filtering Java Streams
Let’s start with an example:
userList.stream()
.filter(user -> user != null)
.filter(user -> !user.isActivated())
.count();
The idea of this code snippet is to count all deactivated users. At first we have to filter all nulls and secondly remove all activated users. The remaining list entries can just be counted.
I want to focus on the two filter
methods. IMHO using method references should be preferred. Let me show that by an example which filters for the opposite. Please keep in mind that this will throw a NullPointerException
since we call isActivated
only on nulls.
userList.stream()
.filter(Objects::isNull)
.filter(User::isActivated)
.count();
Wouldn’t you agree that the method reference User::isActivated
is much easier to read than user -> !user.isActivated()
? But we do not want to filter for activated users, but for de-activated users. We could achieve that be implementing a isDeactivated
method in the User class, but I want to show you a different way.
It’s the very same idea for remove null objects from the list. It’s really nice to just write .filter(Objects::isNull)
to find only nulls, but I always wrote .filter(u -> u != null)
in the past to get only non-nulls.
Until today, I never took the time to look for an easier way. But there are two very nice (and obvious) solutions:
Objects::nonNull
In the Objects class there exists not only the isNull
method, but also nonNull
to achieve exactly the behaviour I need.
userList.stream()
.filter(Objects::nonNull)
.count()
Predicate::not
The Predicate interface has a handy not
method to negate any Predicate. It’s concise and easy to understand when using a static import for the Predicate.not
method
userList.stream()
.filter(not(Objects::isNull))
.filter(not(User::isActivated))
.count();
Predicate.not
is more powerful, it allows to negate any filter option, e.g. to remove empty lists out of a list of lists:
By combining the two approaches, we are again able to use method references to count all deactivated users:
userList.stream()
.filter(Objects::nonNull)
.filter(not(User::isActivated)
.count();
Filtering Java Streams can be very concise by using method references. To achieve the opposite of a provided method, Predicate.not is a handy solution.
Comments are welcome on Twitter.