Orchid
Orchid

Reputation: 223

sort list of objects based on field which can be null

How to to sort list of objects based on field which can be null?

I am trying to do it in following way using Comparator interface and collections sort method. The class is CustomClass and the field on which sorting is to be done is createDate

Comparator comparator=new Comparator<CustomClass>(){
        public int compare(CustomClass o1, CustomClass o2) {
            if(o1.getCreateDate()==null && o2.getCreateDate()==null){
                return 0;
            }
            else if(o1.getCreateDate()==null && o2.getCreateDate()!=null){
                return 1;
            }
            else if(o1.getCreateDate()!=null && o2.getCreateDate()==null){
                return -1;
            }
            else{
                if(o1.getCreateDate().equals(o2.getCreateDate())){
                    return 0;   
                }
                else if(o1.getCreateDate().after(o2.getCreateDate())){
                    return 1;   
                }
                else{
                    return -1;
                }
            }                       
        }
    };

Is there a better way to do it?

Upvotes: 5

Views: 6106

Answers (3)

Mureinik
Mureinik

Reputation: 312116

Assuming getCreateDate() returns an instance of java.util.Date, you can clean up the code a bit. The compareTo's method's contract specifies that it throws a NullPointerException if a date is compared to null (like any Comparable class should do), so you'll have to handle those directly. However, if both are non-null, you shouldn't reimplement the comparing logic, but rely on Date's implementation:

Comparator<CustomClass> comparator = new Comparator<CustomClass>(){
    public int compare(CustomClass o1, CustomClass o2) {
        if (o1.getCreateDate() == null && o2.getCreateDate() == null) {
            return 0;
        }
        else if (o1.getCreateDate() == null && o2.getCreateDate() != null) {
            return 1;
        }
        else if (o1.getCreateDate() != null && o2.getCreateDate() == null) {
            return -1;
        }
        else{
            // Just use java.util.Date's logic:
            return o1.getCreateDate().compareTo(o2.getCreateDate());
        }                       
    }
};

EDIT:

This is quite an old question, but just to complete the picture, in Java 8, the Comparator class itself can do the heavy lifting for you:

Comparator<CustomClass> comparator = 
    Comparator.comparing(CustomClass::getCreateDate, 
                         Comparator.nullsLast(Comparator.naturalOrder()));

Upvotes: 9

Greg Kopff
Greg Kopff

Reputation: 16625

If you're willing to use Google Guava, then you can use ComparisonChain and Ordering to make things more succinct.

public int compare(CustomClass o1, CustomClass o2)
{
  return ComparisonChain.start()
    .compare(o1.getCreateDate(), o2.getCreateDate(), Ordering.natural().nullsLast())
    .result();
}

Upvotes: 6

You do need all of that to ensure that the null values always sort to the end of the list and otherwise you sort by date. You could simplify your code a bit by delegating to the built-in compareTo or by using a declarative Guava Ordering.

Upvotes: 0

Related Questions