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.