Wednesday 3 August 2016

Why do we require empty collections?

As you go through the Collections class, you can come across following method definitions.

Method
Description
public static final <T> List<T> emptyList()
Return an empty immutable list.
public static final <T> Set<T> emptySet()
Returns an empty immutable set.
public static <E> SortedSet<E> emptySortedSet()
Return an empty sorted set.
public static final <K,V> Map<K,V> emptyMap()
Return an empty immutable map.
public static final <K,V> SortedMap<K,V> emptySortedMap()
Return an empty immutable sorted map.
public static final <K,V> NavigableMap<K,V> emptyNavigableMap()

Return an empty immutable navigable map.

Can you think for some time, why do Collections class is providing the methods for empty collections?


Ok let’s come to the point, suppose you had an Employees class, where it is maintaining all the employees information of your company. Your classes looks like below.
public class Employee {
 private int id;
 private String name;

 public Employee(int id, String name) {
  this.id = id;
  this.name = name;
 }

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

}

import java.util.Arrays;
import java.util.List;

public class Employees {
 private List<Employee> employees;

 public Employees() {

 }

 public Employees(Employee... emps) {
  employees = Arrays.asList(emps);
 }

 public void printEmployees() {
  for (Employee emp : employees) {
   System.out.println(emp);
  }
 }

 public List<Employee> getEmployees() {
  return employees;
 }

}

As you closely observe Employees class, there is a flaw in it. If you call the default constructor of Employees class, as per existing design, instance variable 'employees' is not initialized; it has the default value of null. So when you call printEmployees method on Employees instance, you will end up in NullPointerException.


public class Test {

 public static void main(String args[]) {
  Employees emps = new Employees();

  emps.printEmployees();
 }
}


Try to run Test.java, you will end up in NullPointerException.
Exception in thread "main" java.lang.NullPointerException
 at test123.Employees.printEmployees(Employees.java:18)
 at test123.Test.main(Test.java:8)


To resolve above error, update default constructor like below.

public Employees() {
 employees = Collections.emptyList();
}


As you see, I initialized list of employees with empty list.

Following is the complete updated class.

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class Employees {
 private List<Employee> employees;

 public Employees() {
  employees = Collections.emptyList();
 }

 public Employees(Employee... emps) {
  employees = Arrays.asList(emps);
 }

 public void printEmployees() {
  for (Employee emp : employees) {
   System.out.println(emp);
  }
 }

 public List<Employee> getEmployees() {
  return employees;
 }

}


No re run Test.java, it don’t throw any NullPointerException and print nothing. There is a saying like; it is always better to return an empty collection instead of null. In these kind of scenarios, it is better to return empty collections instead of null.

You may like


No comments:

Post a Comment