Objects.isNull() and nonNull()

Use Objects::nonNull and Objects::isNull as ready-made predicates to drop or count nulls in streams and collections.

Signature
public static boolean isNull(Object obj)
public static boolean nonNull(Object obj)
  • Added in Java Java 8

Parameters

ParameterTypeDescription
$objObjectThe value to test. May be null.

Return value

booleanisNull returns true when obj is null. nonNull returns true when obj is not null.

Errors

Never throws.

Objects.isNull(x) is x == null and Objects.nonNull(x) is x != null. That is all they do. They exist so you can pass a null test as a method reference: Objects::nonNull fits anywhere a Predicate is expected.

List<String> emails = users.stream()
        .map(User::email)
        .filter(Objects::nonNull)
        .toList();

Where they help

  • stream.filter(Objects::nonNull) after a map that can return null, such as reading an optional field or looking up a map.
  • list.removeIf(Objects::isNull) to clean a mutable list in place.
  • stream.anyMatch(Objects::isNull) or filter(Objects::isNull).count() to detect or count gaps in imported data.

Compared with the lambda x -> x != null there is no difference in behaviour; the method reference is shorter and reads as a name.

Where they do not

In a plain if, write x == null. The JDK documentation says these methods exist to be used as predicates; if (Objects.isNull(order)) adds a method call and a word without making anything clearer.

Mistakes people make

  • Expecting immutable lists to hold nulls. List.of(a, null) throws, and so does contains(null) on a List.of list. Stream.toList(), by contrast, keeps nulls, so a missing filter(Objects::nonNull) lets them through to the response. Data with nulls usually comes from Arrays.asList, ArrayList, HashMap values or a mapping step.
  • Filtering nulls and losing the reason. Dropping null rows from an import silently hides bad data. Count or log them before filtering.
  • Treating nonNull as "has content". An empty string or empty list passes. Combine with Predicate.not(String::isBlank) when blanks also count as missing.

Back-end angle

These show up wherever data from outside is mapped in bulk: CSV and JSON imports, joining results from several services where some lookups miss, or collecting optional headers. A filter(Objects::nonNull) step before toList() keeps nulls from leaking into responses and later code.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Dropping null results after mapping ids to records through a lookup that misses for unknown ids.
  • Counting null rows in an imported CSV or JSON batch before filtering them, so bad data is reported.
  • Cleaning a mutable list of optional recipients or headers in place with removeIf before sending.

Frequently asked questions

Is Objects.isNull(x) better than x == null?

No, they are identical in behaviour. The methods exist so that a null check can be passed as a method reference, as in filter(Objects::nonNull). In an if statement, x == null is the usual style.

How do I remove null values from a list in Java?

For a mutable list, list.removeIf(Objects::isNull). To get a new list, list.stream().filter(Objects::nonNull).toList().

More examples

Removing nulls from a mutable list in place

removeIf takes a Predicate, and Objects::isNull is exactly that. It returns true because at least one element was removed.

Example · java
void main() {
    var recipients = new ArrayList<>(Arrays.asList("[email protected]", null, "[email protected]", null));
    boolean changed = recipients.removeIf(Objects::isNull);
    IO.println(changed + " " + recipients);
}
// Output:
// true [[email protected], [email protected]]

Joining lookups where some keys miss

Map.get returns null for a missing id, so the nonNull filter keeps the response clean. Reporting the unknown ids separately with containsKey means the gaps are not silently lost.

Example · java
final Map<Long, String> namesById = Map.of(1L, "Ada", 3L, "Lin");

void main() {
    List<Long> ids = List.of(1L, 2L, 3L, 4L);

    List<String> names = ids.stream()
            .map(namesById::get)
            .filter(Objects::nonNull)
            .toList();

    List<Long> unknown = ids.stream()
            .filter(id -> !namesById.containsKey(id))
            .toList();

    IO.println(names);
    IO.println("unknown ids: " + unknown);
}
// Output:
// [Ada, Lin]
// unknown ids: [2, 4]

Null versus blank

nonNull keeps empty and whitespace-only strings. Adding Predicate.not(String::isBlank) drops them as well when they should count as missing.

Example · java
void main() {
    List<String> headers = Arrays.asList("gzip", null, "", "  ", "br");

    IO.println(headers.stream().filter(Objects::nonNull).toList());
    IO.println(headers.stream()
            .filter(Objects::nonNull)
            .filter(Predicate.not(String::isBlank))
            .toList());
}
// Output:
// [gzip, ,   , br]
// [gzip, br]

Discussion

  • Be the first to comment on this lesson.