Java
Null Validation
Empty Collections
Best Practices
Java Programming

Best practice to validate null and empty collection in Java

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

The best practice in Java is usually to avoid null collections altogether and use empty collections to represent "no items." When you cannot guarantee that, the next best approach is to centralize the null and emptiness check in simple, readable code rather than scattering inconsistent checks across the codebase.

Prefer Empty Collections Over null

If you control the API, return an empty collection instead of null. That removes an entire class of defensive checks from calling code.

java
1import java.util.Collections;
2import java.util.List;
3
4public class UserService {
5    public List<String> findRoles(String userId) {
6        return Collections.emptyList();
7    }
8}

Now callers can safely use isEmpty, iterate, or stream the result without checking for null first.

Use the Plain Java Check When Needed

If null is still possible, the standard check is short and perfectly acceptable.

java
1import java.util.Collection;
2
3public static boolean isNullOrEmpty(Collection<?> values) {
4    return values == null || values.isEmpty();
5}

This is usually all you need. It is clear, fast, and has no external dependency cost.

Validate at the Boundary, Not Everywhere

The cleanest place to normalize null or reject it is at a boundary:

  • request mapping layer
  • repository adapter
  • constructor
  • setter or factory method

Once the data is normalized, the rest of the system can work with normal collections instead of mixed null and empty semantics.

java
1import java.util.List;
2import java.util.Objects;
3
4public record BatchRequest(List<String> ids) {
5    public BatchRequest {
6        ids = Objects.requireNonNullElse(ids, List.of());
7    }
8}

That keeps the null-handling rule in one place instead of repeating it in every consumer.

Be Careful with Utility Libraries

Libraries such as Apache Commons Collections provide helpers like CollectionUtils.isEmpty(collection). Those are convenient if the dependency is already present, but they are not necessary for something this small.

The key question is consistency, not cleverness. A simple in-house utility or direct Java check is usually enough.

Avoid Overusing Optional for Collections

An Optional<List<T>> is often a smell because the collection itself already has an "empty" state. Most of the time, List<T> with an empty list is simpler than mixing Optional and collection semantics together.

java
public List<String> searchTags(String query) {
    return List.of();
}

This is generally easier to consume than Optional<List<String>>.

Make the Semantic Meaning Explicit

Sometimes null and empty do mean different things. For example:

  • 'null might mean "value not provided"'
  • empty might mean "provided, but intentionally contains no items"

If that distinction matters, encode it explicitly in the API or surrounding model instead of letting callers guess. The correct best practice depends on the business meaning, not on style alone.

Prefer One Shared Helper If the Pattern Repeats

If your codebase checks collections constantly, create one tiny helper and standardize on it. That keeps the intent obvious and avoids half a dozen slightly different versions of the same validation rule.

Common Pitfalls

  • Returning null collections from APIs when an empty collection would work better.
  • Repeating collection != null && !collection.isEmpty() everywhere instead of normalizing earlier.
  • Introducing Optional<Collection<T>> where a plain collection would be clearer.
  • Using a library helper for trivial checks without any consistency benefit.
  • Ignoring cases where null and empty actually have different business meanings.

Summary

  • Prefer empty collections over null whenever you control the API.
  • When null is possible, collection == null || collection.isEmpty() is a good default check.
  • Normalize or validate collections at system boundaries to reduce repeated checks.
  • Avoid Optional<Collection<T>> in most cases.
  • Let business meaning, not habit, determine whether null and empty should be treated the same.

Course illustration
Course illustration

All Rights Reserved.