How to Check If a Collection Is Null in Java

JavaJavaBeginner
Practice Now

Introduction

In this lab, you will learn how to effectively handle null values when working with collections in Java. Collections are fundamental data structures, and it's crucial to write robust code that can safely manage situations where a collection variable might be null. You will explore how to test for null collections, combine null and empty checks for comprehensive validation, and leverage the Optional class for enhanced null safety, ultimately helping you avoid common NullPointerException errors.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL java(("Java")) -.-> java/BasicSyntaxGroup(["Basic Syntax"]) java(("Java")) -.-> java/DataStructuresGroup(["Data Structures"]) java(("Java")) -.-> java/ObjectOrientedandAdvancedConceptsGroup(["Object-Oriented and Advanced Concepts"]) java/BasicSyntaxGroup -.-> java/if_else("If...Else") java/DataStructuresGroup -.-> java/collections_methods("Collections Methods") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/classes_objects("Classes/Objects") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/exceptions("Exceptions") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/arraylist("ArrayList") subgraph Lab Skills java/if_else -.-> lab-559942{{"How to Check If a Collection Is Null in Java"}} java/collections_methods -.-> lab-559942{{"How to Check If a Collection Is Null in Java"}} java/classes_objects -.-> lab-559942{{"How to Check If a Collection Is Null in Java"}} java/exceptions -.-> lab-559942{{"How to Check If a Collection Is Null in Java"}} java/arraylist -.-> lab-559942{{"How to Check If a Collection Is Null in Java"}} end

Test Collection for Null

In this step, we will explore how to handle null values when working with collections in Java. Collections, like List or Set, are fundamental data structures, and it's crucial to write code that can safely handle situations where a collection variable might be null.

A null value in Java means that a variable does not refer to any object. If you try to access methods or properties of a null object, your program will crash with a NullPointerException. This is a very common error in Java, and learning how to avoid it is essential.

Let's start by creating a simple Java program that demonstrates the problem.

  1. Open the HelloJava.java file in the WebIDE editor if it's not already open.

  2. Replace the entire contents of the file with the following code:

    import java.util.List;
    
    public class HelloJava {
        public static void main(String[] args) {
            List<String> names = null; // Intentionally set to null
    
            // This line will cause a NullPointerException if names is null
            // int size = names.size();
            // System.out.println("Size of the list: " + size);
    
            System.out.println("Program finished.");
        }
    }

    In this code, we declare a List of strings called names and explicitly set it to null. The commented-out lines show what would happen if we tried to call the size() method on a null list โ€“ it would result in a NullPointerException.

  3. Save the file (Ctrl+S or Cmd+S).

  4. Now, let's compile the program. Open the Terminal at the bottom of the WebIDE and make sure you are in the ~/project directory. Run the following command:

    javac HelloJava.java

    You should see no output if the compilation is successful.

  5. Now, run the program:

    java HelloJava

    You should see the output:

    Program finished.

    Since the line that would cause the NullPointerException is commented out, the program runs without crashing.

Now, let's modify the code to check for null before trying to use the collection.

  1. Open HelloJava.java again in the editor.

  2. Modify the main method to include a null check:

    import java.util.List;
    
    public class HelloJava {
        public static void main(String[] args) {
            List<String> names = null; // Intentionally set to null
    
            if (names != null) {
                // This code will only run if names is NOT null
                int size = names.size();
                System.out.println("Size of the list: " + size);
            } else {
                System.out.println("The list is null.");
            }
    
            System.out.println("Program finished.");
        }
    }

    We've added an if statement that checks if names is not equal to null (names != null). The code to get the size and print it is now inside this if block, meaning it will only execute if names is a valid list object. The else block handles the case where names is null.

  3. Save the file.

  4. Compile the modified program:

    javac HelloJava.java
  5. Run the program again:

    java HelloJava

    This time, you should see the output:

    The list is null.
    Program finished.

    The program correctly identified that the list was null and printed the appropriate message, avoiding the NullPointerException.

This simple if (collection != null) check is the most basic way to prevent NullPointerException when dealing with collections. It's a fundamental technique that you will use frequently in Java programming.

Combine Null and Empty Checks

In the previous step, we learned how to check if a collection is null. However, a collection can also be empty (contain no elements) even if it's not null. In many cases, you might want to treat a null collection and an empty collection similarly, or at least handle both possibilities.

Checking if a collection is empty is done using the isEmpty() method. This method returns true if the collection contains no elements and false otherwise.

Let's modify our program to demonstrate the difference between a null list and an empty list, and then combine the checks.

  1. Open the HelloJava.java file in the WebIDE editor.

  2. Replace the contents with the following code:

    import java.util.List;
    import java.util.ArrayList; // Import ArrayList
    
    public class HelloJava {
        public static void main(String[] args) {
            List<String> nullList = null; // Intentionally set to null
            List<String> emptyList = new ArrayList<>(); // An empty list
    
            System.out.println("Checking nullList:");
            if (nullList != null) {
                System.out.println("nullList is not null.");
                if (nullList.isEmpty()) {
                    System.out.println("nullList is empty.");
                } else {
                    System.out.println("nullList is not empty.");
                }
            } else {
                System.out.println("nullList is null.");
            }
    
            System.out.println("\nChecking emptyList:");
            if (emptyList != null) {
                System.out.println("emptyList is not null.");
                if (emptyList.isEmpty()) {
                    System.out.println("emptyList is empty.");
                } else {
                    System.out.println("emptyList is not empty.");
                }
            } else {
                System.out.println("emptyList is null.");
            }
    
            System.out.println("\nProgram finished.");
        }
    }

    We've added an emptyList which is initialized as a new, empty ArrayList. We then perform the same null and empty checks on both nullList and emptyList to see the difference in output.

  3. Save the file.

  4. Compile the program in the Terminal:

    javac HelloJava.java
  5. Run the program:

    java HelloJava

    You should see output similar to this:

    Checking nullList:
    nullList is null.
    
    Checking emptyList:
    emptyList is not null.
    emptyList is empty.
    
    Program finished.

    This output clearly shows that nullList is null, while emptyList is not null but is empty.

Now, let's combine the null and empty checks into a single condition. A common pattern is to check if a collection is either null or empty.

  1. Open HelloJava.java in the editor.

  2. Modify the main method to combine the checks:

    import java.util.List;
    import java.util.ArrayList;
    
    public class HelloJava {
        public static void main(String[] args) {
            List<String> names = null; // Can be null or an empty list
    
            // Combined check: is names null OR is names empty?
            if (names == null || names.isEmpty()) {
                System.out.println("The list is null or empty.");
            } else {
                System.out.println("The list is not null and not empty.");
                // You can safely iterate or access elements here
                // For example:
                // System.out.println("First element: " + names.get(0));
            }
    
            // Let's test with an empty list
            List<String> anotherList = new ArrayList<>();
            System.out.println("\nChecking anotherList (empty):");
            if (anotherList == null || anotherList.isEmpty()) {
                System.out.println("anotherList is null or empty.");
            } else {
                System.out.println("anotherList is not null and not empty.");
            }
    
            // Let's test with a non-empty list
            List<String> populatedList = new ArrayList<>();
            populatedList.add("Item 1");
            System.out.println("\nChecking populatedList (not empty):");
            if (populatedList == null || populatedList.isEmpty()) {
                System.out.println("populatedList is null or empty.");
            } else {
                System.out.println("populatedList is not null and not empty.");
            }
    
    
            System.out.println("\nProgram finished.");
        }
    }

    We use the logical OR operator (||) to combine the conditions names == null and names.isEmpty(). The if block will execute if either condition is true. We also added tests with an empty list and a populated list to see how the combined check behaves.

    Important Note: The order of the conditions in names == null || names.isEmpty() is crucial. If names is null, the first part of the condition (names == null) is true. Because of short-circuit evaluation in Java, the second part (names.isEmpty()) is not evaluated, preventing a NullPointerException. If you wrote names.isEmpty() || names == null, and names was null, calling names.isEmpty() would cause a NullPointerException. Always check for null first when combining with other checks on the object.

  3. Save the file.

  4. Compile the program:

    javac HelloJava.java
  5. Run the program:

    java HelloJava

    You should see output similar to this:

    The list is null or empty.
    
    Checking anotherList (empty):
    anotherList is null or empty.
    
    Checking populatedList (not empty):
    populatedList is not null and not empty.
    
    Program finished.

    This demonstrates how the combined check correctly identifies null and empty lists, and distinguishes them from non-empty lists. This combined check is a very common and safe way to handle collections that might be null or empty.

Use Optional for Null Safety

In this step, we will explore a more modern approach to handling potential null values in Java using the Optional class, introduced in Java 8. Optional is a container object that may or may not contain a non-null value. It provides a way to represent the presence or absence of a value more explicitly, which can help reduce the risk of NullPointerExceptions.

While if (collection != null) checks are perfectly valid and necessary in many situations, Optional can make your code more readable and expressive, especially when dealing with methods that might return a value or might return null.

Let's see how we can use Optional with a collection. Although Optional is typically used for single values, you might encounter scenarios where a method returns an Optional<List<SomeObject>>.

  1. Open the HelloJava.java file in the WebIDE editor.

  2. Replace the contents with the following code that demonstrates using Optional with a potentially null list:

    import java.util.List;
    import java.util.ArrayList;
    import java.util.Optional; // Import Optional
    
    public class HelloJava {
    
        // A method that might return an Optional containing a list, or an empty Optional
        public static Optional<List<String>> getNames(boolean includeNames) {
            if (includeNames) {
                List<String> names = new ArrayList<>();
                names.add("Alice");
                names.add("Bob");
                return Optional.of(names); // Return an Optional containing the list
            } else {
                return Optional.empty(); // Return an empty Optional
            }
        }
    
        public static void main(String[] args) {
            // Case 1: Get names when includeNames is true
            Optional<List<String>> namesOptional1 = getNames(true);
    
            System.out.println("Checking namesOptional1:");
            // Check if the Optional contains a value
            if (namesOptional1.isPresent()) {
                List<String> names = namesOptional1.get(); // Get the list from the Optional
                System.out.println("List is present. Size: " + names.size());
                // You can also check if the list itself is empty
                if (names.isEmpty()) {
                    System.out.println("List is empty.");
                } else {
                    System.out.println("List is not empty. First name: " + names.get(0));
                }
            } else {
                System.out.println("List is not present (Optional is empty).");
            }
    
            System.out.println("---");
    
            // Case 2: Get names when includeNames is false
            Optional<List<String>> namesOptional2 = getNames(false);
    
            System.out.println("Checking namesOptional2:");
            if (namesOptional2.isPresent()) {
                List<String> names = namesOptional2.get();
                System.out.println("List is present. Size: " + names.size());
                if (names.isEmpty()) {
                    System.out.println("List is empty.");
                } else {
                    System.out.println("List is not empty. First name: " + names.get(0));
                }
            } else {
                System.out.println("List is not present (Optional is empty).");
            }
    
    
            System.out.println("\nProgram finished.");
        }
    }

    In this code:

    • We define a method getNames that returns an Optional<List<String>>. This method simulates a scenario where you might get a list, or you might get nothing (represented by an empty Optional).
    • In the main method, we call getNames with true and false to test both cases.
    • We use namesOptional.isPresent() to check if the Optional contains a list.
    • If isPresent() is true, we use namesOptional.get() to retrieve the list. This is safe because we've already checked for presence.
    • Inside the isPresent() block, we can then perform checks on the list itself, such as names.isEmpty().
  3. Save the file.

  4. Compile the program in the Terminal:

    javac HelloJava.java
  5. Run the program:

    java HelloJava

    You should see output similar to this:

    Checking namesOptional1:
    List is present. Size: 2
    List is not empty. First name: Alice
    ---
    Checking namesOptional2:
    List is not present (Optional is empty).
    
    Program finished.

    This output shows how Optional helps us handle the case where a list might not be returned at all.

Optional also provides other useful methods for handling the absence of a value, such as:

  • orElse(defaultValue): Returns the value if present, otherwise returns a default value.
  • orElseGet(supplier): Returns the value if present, otherwise returns the result of the supplier function.
  • orElseThrow(exceptionSupplier): Returns the value if present, otherwise throws an exception produced by the exceptionSupplier.
  • ifPresent(consumer): Performs the given action if a value is present.

Let's modify the code to use ifPresent for a more concise way to handle the list when it's present.

  1. Open HelloJava.java in the editor.

  2. Modify the main method to use ifPresent:

    import java.util.List;
    import java.util.ArrayList;
    import java.util.Optional;
    
    public class HelloJava {
    
        public static Optional<List<String>> getNames(boolean includeNames) {
            if (includeNames) {
                List<String> names = new ArrayList<>();
                names.add("Alice");
                names.add("Bob");
                return Optional.of(names);
            } else {
                return Optional.empty();
            }
        }
    
        public static void main(String[] args) {
            // Case 1: Get names when includeNames is true
            Optional<List<String>> namesOptional1 = getNames(true);
    
            System.out.println("Checking namesOptional1 using ifPresent:");
            namesOptional1.ifPresent(names -> {
                // This block only runs if namesOptional1 contains a list
                System.out.println("List is present. Size: " + names.size());
                if (names.isEmpty()) {
                    System.out.println("List is empty.");
                } else {
                    System.out.println("List is not empty. First name: " + names.get(0));
                }
            });
            if (!namesOptional1.isPresent()) { // Still need a check if you need to handle the absence case
                 System.out.println("List is not present (Optional is empty).");
            }
    
    
            System.out.println("---");
    
            // Case 2: Get names when includeNames is false
            Optional<List<String>> namesOptional2 = getNames(false);
    
            System.out.println("Checking namesOptional2 using ifPresent:");
             namesOptional2.ifPresent(names -> {
                System.out.println("List is present. Size: " + names.size());
                if (names.isEmpty()) {
                    System.out.println("List is empty.");
                } else {
                    System.out.println("List is not empty. First name: " + names.get(0));
                }
            });
             if (!namesOptional2.isPresent()) {
                 System.out.println("List is not present (Optional is empty).");
             }
    
    
            System.out.println("\nProgram finished.");
        }
    }

    We replaced the if (namesOptional.isPresent()) { ... namesOptional.get() ... } structure with namesOptional.ifPresent(names -> { ... }). The code inside the lambda expression (names -> { ... }) will only execute if the Optional contains a value. We still added an if (!namesOptional.isPresent()) check to handle the case where the Optional is empty, as ifPresent only handles the presence case.

  3. Save the file.

  4. Compile the program:

    javac HelloJava.java
  5. Run the program:

    java HelloJava

    The output should be the same as before, demonstrating that ifPresent provides an alternative way to handle the presence of a value in an Optional.

Using Optional can make your code's intent clearer regarding whether a value might be absent, and it encourages you to handle that absence explicitly, reducing the likelihood of unexpected NullPointerExceptions.

Summary

In this lab, we learned how to handle null collections in Java to prevent NullPointerException. We started by demonstrating the problem of calling methods on a null collection, which leads to a runtime error.

We then explored different techniques to safely check if a collection is null before attempting to access its elements or properties. This is a fundamental skill for writing robust and error-free Java code.