Sorting in Java is easy:

public class Data { private final String value ; public Data ( String value ) { this . value = value ; } public String getValue () { return value ; } @Override public String toString () { return String . format ( "Data(%s)" , this . value ); } } public static void main ( String [] args ) { List < Data > listOfData = Arrays . asList ( new Data ( "foo" ), new Data ( "bar" ), new Data ( "nyu" )); listOfData . sort ( comparing ( Data: : getValue )); listOfData . forEach ( System . out :: println ); } //OUTPUT: // Data(bar) // Data(foo) // Data(nyu)

…unless we try to sort a collection containing null values:

List < Data > listOfData = Arrays . asList ( new Data ( "foo" ), null , new Data ( "bar" ), new Data ( "nyu" )); listOfData . sort ( comparing ( Data: : getValue )); listOfData . forEach ( System . out :: println ); //OUTPUT: // Exception in thread "main" java.lang.NullPointerException // at java.util.Comparator.lambda$comparing$77a9974f$1(Comparator.java:469)

Fortunately there is easy solution to this problem. But first we must decide whenever we want null s to be first or last in sorted collection. After we made our mind we may use nifty nullsFirst or nullsLast decorators provided by Comparator interface:

import static java . util . Comparator .*; List < Data > listOfData = Arrays . asList ( new Data ( "foo" ), null , new Data ( "bar" ), new Data ( "nyu" )); listOfData . sort ( nullsFirst ( comparing ( Data: : getValue ))); listOfData . forEach ( System . out :: println ); //OUTPUT: // null // Data(bar) // Data(foo) // Data(nyu)

nullsFirst is great example of decorator design pattern (it adds functionality but doesn’t change interface). nullsFirst works by wrapping provided comparator in code similar to:

public static < T > Comparator < T > nullsFirst ( Comparator < T > comparator ) { return ( a , b ) -> { if ( a == null ) return ( b == null ) ? 0 : - 1 ; if ( b == null ) return 1 ; // a and b are not null here return comparator . compare ( a , b ); }; }

Previous example works great unless we try to sort a collection containing Data(null) :

List < Data > listOfData = Arrays . asList ( new Data ( "foo" ), new Data ( null ), new Data ( "bar" ), new Data ( "nyu" )); listOfData . sort ( nullsFirst ( comparing ( Data: : getValue ))); listOfData . forEach ( System . out :: println ); //OUTPUT: // Exception in thread "main" java.lang.NullPointerException // at java.util.Comparator.lambda$comparing$77a9974f$1(Comparator.java:469) // at java.util.Comparators$NullComparator.compare(Comparators.java:83)

But do not despair nullsFirst can help us again:

listOfData . sort ( nullsFirst ( comparing ( Data: : getValue , nullsFirst ( naturalOrder ())))); listOfData . forEach ( System . out :: println ); //OUTPUT: // Data(null) // Data(bar) // Data(foo) // Data(nyu)

Ta da! It works but readability suffers greatly… You may ask what is this thing:

comparing ( Data: : getValue , nullsFirst ( naturalOrder ()))

First: we use the following overload of comparing method:

public static < T , U > Comparator < T > comparing ( Function <? super T , ? extends U > keyExtractor , Comparator <? super U > keyComparator ) { return ( c1 , c2 ) -> keyComparator . compare ( keyExtractor . apply ( c1 ), keyExtractor . apply ( c2 )); }

Second: in our example nullsFirst(naturalOrder()) is a comparator that can compare nullable String s:

Comparator < String > cmp = nullsFirst ( naturalOrder ()); cmp . compare ( "foo" , "zzz" ); // -1 cmp . compare ( "foo" , null ); // 1

Now everything should be clear (I hope).