Return Empty Collections and/or Unmodifiable Collections

1. Introduction

In this article we will see about best practices for returning collections. It is common thing to return null from a method whose return type is collection. Returning null leads client to write null safe code. Not to mention null checks are clutter in code and should be avoided as much as possible.

2. Return empty Collections

It is not uncommon to see below code. It processes the List<Transaction> if the List is not null and returns the result List. If the input transactions is null then null is returned.

/**
  * returns a list containing Transactions or null
  * if input transactions is null.
  * */
public List<Transaction> filterTxns(
     List<Transaction> transactions, 
     Predicate<Transaction> pred) {

     if(transactions != null) {
         List<Transaction> result = new ArrayList<>();
         // process and add elements to result List.
         for(Transaction transaction : transactions) {
             if(pred.test(transaction)) {
                 result.add(transaction); 
             }
         }
         return result;
     }
     return null;
}

Client code looks something like this

List<Transaction> result = filterTxns(txns, Objects::nonNull);
if(result != null) {
    // do something
}

Client needs to check for null every time the method is called as there is no guarantee that the method will return appropriate data. This is error prone as client might forget to check for null and it might cause issue later in time. Also returning null is nothing more than a clutter. It might be advisable to return null in some cases but it hard to argue to return null if the return type is a Collection.

We can refactor the method filterTxns as belows:

/**
  * returns a list containing Transactions or null
  * if input transactions is null.
  * */
public List<Transaction> filterTxns(
     List<Transaction> transactions, 
     Predicate<Transaction> pred) {

    if (transactions == null) {
        return Collections.emptyList();
    }
    List<Transaction> result = new ArrayList<>();
    // test and add elements to result List
    for(Transaction transaction : transactions) {
        if(pred.test(transaction)) {
            result.add(transaction); 
        }
    }
    return Collections.unmodifiableList(result);
}

Now client need not check for null after getting result from getTxns() method. Also, it would be advisable to return a unmodifiable collection as if the Collection is not unmodifiable then the client may add values to the result hence corrupting the data.

3. Conclusion

In this article, we learnt about returning an empty collections as against returning nulls. Returning nulls creates an unnecessary clutter on client code and it is susceptible to causing NullPointerException if client doesn’t code defensively. In most cases it is better to return empty or unmodifiable collections as against null or modifiable collections.

Leave a Reply

Your email address will not be published. Required fields are marked *