user1438038
user1438038

Reputation: 6079

How to handle null values when doing Collections.sort() with nested objects?

What is the best way to deal with null values, when doing Collections.sort() on nested objects?

I'd like to sort a couple of objects, basically applying this rule:

@Override
public int compare(final InvoicePos invoicePosOne, final InvoicePos invoicePosTwo) {
   return invoicePosOne.getInvoice().getInvoiceNo().compareTo(invoicePosTwo.getInvoice().getInvoiceNo());
}

However, any of these objects can be null (i.e. invoice position, invoice and invoice number).

public class InvoicePos {
  private Invoice invoice = null;

  // ...
}

public class Invoice {
  private String invoiceNo = "";

  // ...
}

Do I have do do explicit null-checks on all my objects or is there an approach with less writing?


For clarification: I'm aware that my above example may raise NullPointerExceptions. Currently I'm doing the following and basically, I questioned myself, if there is any smarter approach.

     Collections.sort(allInvoicePositions, new Comparator<InvoicePos>() {
        @Override
        public int compare(final InvoicePos invoicePosOne, final InvoicePos invoicePosTwo) {
           if (null == invoicePosOne && null == invoicePosTwo) {
              return 0;
           }

           if (null == invoicePosOne) {
              return -1;
           }

           if (null == invoicePosTwo) {
              return 1;
           }

           if (null == invoicePosOne.getInvoice() && null == invoicePosTwo.getInvoice()) {
              return 0;
           }

           if (null == invoicePosOne.getInvoice()) {
              return -1;
           }

           if (null == invoicePosTwo.getInvoice()) {
              return 1;
           }

           if (null == invoicePosOne.getInvoice().getInvoiceNo() && null == invoicePosTwo.getInvoice().getInvoiceNo()) {
              return 0;
           }

           if (null == invoicePosOne.getInvoice().getInvoiceNo()) {
              return -1;
           }

           if (null == invoicePosTwo.getInvoice().getInvoiceNo()) {
              return 1;
           }

           return invoicePosOne.getInvoice().getInvoiceNo().compareTo(invoicePosTwo.getInvoice().getInvoiceNo());
        }
     });

Upvotes: 2

Views: 1989

Answers (3)

Simone
Simone

Reputation: 2311

If you have null values then you need to handle them explicitly and in a consistent way so to have a valid ordering relation. That is, something like:

compare (a, b) {
  if (a == null && b == null) return 0;      
  if (a == null) return -1;
  if (b == null) return +1;
  return comp(a,b);
}

Don't be tempted to do something like:

compare (a, b) {
  if (a == null || b == null) return -1;
  return comp(a,b);
}

which would break the ordering relation.

Upvotes: 0

Kalaiarasan Manimaran
Kalaiarasan Manimaran

Reputation: 1658

There is something called as NullComparator in org.apache.commons.collections.jar.

This might help you https://commons.apache.org/proper/commons-collections/javadocs/api-2.1.1/org/apache/commons/collections/comparators/NullComparator.html.

Upvotes: 1

Maroun
Maroun

Reputation: 96018

Do I have do do explicit null-checks on all my objects or is there an approach with less writing?

If these values don't represent anything in your collection, then the best thing you can do is avoid them; don't allow inserting them, so you won't have to handle them when comparing items.

If you insist to have them, then you must check if they're null to avoid NullPointerException.

Upvotes: 1

Related Questions