Objects.isNull() and nonNull()
Use Objects::nonNull and Objects::isNull as ready-made predicates to drop or count nulls in streams and collections.
public static boolean isNull(Object obj)
public static boolean nonNull(Object obj)- Added in Java Java 8
Parameters
| Parameter | Type | Description |
|---|---|---|
$obj | Object | The 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 amapthat 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)orfilter(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 doescontains(null)on aList.oflist.Stream.toList(), by contrast, keeps nulls, so a missingfilter(Objects::nonNull)lets them through to the response. Data with nulls usually comes fromArrays.asList,ArrayList,HashMapvalues 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
nonNullas "has content". An empty string or empty list passes. Combine withPredicate.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
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.
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.
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.
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