Have you ever wondered why the java.util.Collections class includes various " empty " class methods, which return immutable empty collections and immutable empty iterators? This post answers this question.

Why are the returned empty collections and iterators immutable? The returned empty collections and empty iterators are immutable (unchangeable) so that they can be safely used in multithreaded contexts.

An immutable empty list of flowers

The Collections class's various " empty " class methods offer a useful alternative to returning null (and avoiding potential java.lang.NullPointerException s from being thrown) in certain contexts. Listing 1 presents the source code to an application that demonstrates the benefit of an immutable empty list.

Listing 1. Empty and nonempty List s of Flower s

import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; class Flowers { private List<String> flowers; Flowers() { flowers = Collections.emptyList(); } Flowers(String... flowerNames) { flowers = new ArrayList<String>(); for (String flowerName: flowerNames) flowers.add(flowerName); } @Override public String toString() { return flowers.toString(); } } public class EmptyListDemo { public static void main(String[] args) { Flowers flowers = new Flowers(); System.out.println(flowers); flowers = new Flowers("Rose", "Violet", "Marigold"); System.out.println(flowers); } }

Listing 1 declares a Flowers class that stores the names of various flowers in a list. This class provides two constructors: a noargument constructor and a constructor that takes a variable number of java.lang.String arguments identifying various flowers.

The noargument constructor invokes <T> List<T> emptyList() to initialize its private flowers field to an empty java.util.List of String -- emptyList() is a generic method and the compiler infers its return type from its context.

If you're wondering about the need for emptyList() , examine the toString() method. Notice that this method evaluates flowers.toString() . If you didn't assign a reference to an empty List<String> to flowers , flowers would contain the null reference (the default value for this instance field when the object is created), and a NullPointerException object would be thrown when attempting to evaluate flowers.toString() .

Compile Listing 1 as follows:

javac EmptyListDemo.java

Run the resulting application as follows:

java EmptyListDemo

You should observe the following output:

[] [Rose, Violet, Marigold]

emptyList() 's implementation emptyList() is implemented as return (List<T>) EMPTY_LIST; , which returns the single List object assigned to the EMPTY_LIST class field in the Collections class. You might want to work with EMPTY_LIST directly, but you'll run into an unchecked warning message if you do, because EMPTY_LIST is declared to be of the raw type List , and mixing raw and generic types leads to such messages. Although you could suppress the warning, you're better off using the emptyList() method.

An immutable empty iterator of to-do tasks

Most of the " empty " methods return immutable empty collections, but three methods return immutable empty iterators: <T> Enumeration<T> emptyEnumeration() (classic iteration method), <T> Iterator<T> emptyIterator() , and <T> ListIterator<T> emptyListIterator() . Listing 2 demonstrates the need for an immutable empty iterator.

Listing 2. NullPointerException arising from the null reference in todoList

import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; class ToDo { private String task; private String date; ToDo(String task, String date) { this.task = task; this.date = date; } @Override public String toString() { return task + ": "+ date; } } class ToDoList { private List<ToDo> todoList; void add(ToDo todo) { if (todoList == null) todoList = new ArrayList<>(); todoList.add(todo); } public Iterator<ToDo> iterator() { return todoList.iterator(); } } public class EmptyIteratorDemo { public static void main(String[] args) { ToDoList todoList = new ToDoList(); //todoList.add(new ToDo("Mow the lawn", "April 5, 10 AM")); Iterator<ToDo> todos = todoList.iterator(); while (todos.hasNext()) System.out.println(todos.next()); } }

Listing 2 presents ToDo and ToDoList classes that describe individual and lists of to-do tasks in terms of task name and date by which the task should have been performed. ToDoList 's add() method lazily initializes the list. Unfortunately, this lazy initialization can result in a thrown NullPointerException object.

NullPointerException arises when toDoList.iterator() in ToDoList 's iterator() method is executed and toDoList contains the null reference because add() hasn't been called. Compiling Listing 2 ( javac EmptyIteratorDemo.java ) and running the application ( java EmptyIteratorDemo ) results in the following output:

Exception in thread "main" java.lang.NullPointerException at ToDoList.iterator(EmptyIteratorDemo.java:37) at EmptyIteratorDemo.main(EmptyIteratorDemo.java:47)

You can avoid the exception by uncommenting the toDoList.add() call in the main() method. Better still, you can modify ToDoList 's iterator() method to return the result of calling Collections.emptyIterator() when toDoList contains the null reference, as follows:

public Iterator<ToDo> iterator() { return (todoList != null) ? todoList.iterator() : Collections.emptyIterator(); }

Additional thoughts on the example In this contrived example, it would be better to assign a new java.util.ArrayList object to the todoList field, as in private List<ToDo> todoList; , and forget about emptyIterator() and NullPointerException . However, you might encounter more practical situations where you'll need to work with an empty-iteration method.

Conclusion

The Collections class's various " empty " class methods can help you write safer code that avoids thrown NullPointerExceptions . They can also help you write more streamlined code because you don't always have to test for null references. For example, Listing 1's toString() method specifies return flowers.toString(); instead of having to specify the longer return (flowers != null) ? flowers.toString() : ""; .

download Download the source Get the source code for this post's applications. Created by Jeff Friesen for JavaWorld

The following software was used to develop the post's code:

64-bit JDK 8u60

The post's code was tested on the following platform(s):

JVM on 64-bit Windows 8.1

This story, "Immutable empty collections and iterators" was originally published by JavaWorld .