Sorting a List having null values with Comparator’s nullsFirst
Hello Friends,
In this tutorial, we will see how we can sort a list of items when few of the items are null in the list using Java 8 Comparator.nullsFirst, such that nulls are treated as smallest elements in the list.
– What is Comparator
– What is nullsFirst method doing in Comparator
– Sorting a list of Strings having non null names
– Sorting a list of Strings having names and Nulls without using nullsFirst
– Solving above problem by sorting the list using nullsFirst method
– Sorting a list of Custom objects without nulls
– Sorting a list of Custom objects with nulls without using nullsFirst
– Solving above problem by sorting the list using nullsFirst method
– Sorting the list having employee with name as null
What is a Comparator?
Comparator is a FunctionalInterface which has following abstract method
int compare(T
o1, T
o2);
So if you want to sort ,say your list.You can create a class implementing Comparator interface’s compare method, wherein you can define the logic of sorting and pass this comparator to the list.sort() method and it will then sort according to your defined logic.
Alternatively, rather than creating a separate class implementing Comparator interface, you can pass lambda function(implementing compare method of Comparator) to list.sort() method.
What is nullsFirst method doing in Comparator?
In Java 8, there has been addition of lots of default and static methods in Comparator interface.
nullsFirst is one of the static method defined in the Comparator interface having following signature :
public
static <T> Comparator<T> nullsFirst(Comparator<?
super T>
comparator)
So what does it do ?
– Returns a null-friendly comparator that considers null to be less than non null.
– When both objects are null, they are considered equal.
– When both are non null, the specified comparator, which is passed to nullsFirst method as parameter, is used to determined the sort order
– When the specified comparator is null, then the returned comparator consider all non null values to be equal.
To understand the usage of nullsFirst , let us try to sort a list of Strings having name of employees ,
– First without null values
– Then with null values but without nullsFirst
– Then with null values and with nullsFirst
– Then we will do same above steps for a custom Employee object
– And then we will see what if one of the property on the basis of which sorting needs to be done, is null in a custom object
Sorting a list of Strings having non null names
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 | package com.blogspot.javasolutionsguide; import java.util.Arrays; import java.util.List; import java.util.Comparator; public class ComparatorTestWithListOfNamesWithoutNulls { public static void main(String[] args) { List<String> names = Arrays.asList( "Gaurav" , "Tendulkar" , "Suresh" , "Rohit" , "Bumrah" ); System.out.println( "Before Sorting:" ); names.forEach(System.out ::println); names.sort(Comparator.naturalOrder()); System.out.println( "After Sorting:" ); names.forEach(System.out ::println); } |
1 | } |
Here is the output :
Before Sorting:
Gaurav
Tendulkar
Suresh
Rohit
Bumrah
After Sorting:
Bumrah
Gaurav
Rohit
Suresh
Tendulkar
Sorting a list of Strings having names and nulls without using nullsFirst
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 | package com.blogspot.javasolutionsguide; import java.util.Arrays; import java.util.Comparator; import java.util.List; public class ComparatorTestWithListOfNamesAndNulls { public static void main(String[] args) { List<String> names = Arrays.asList( "Gaurav" , null , "Sachin" , "Suresh" , null , "Rohit" , "Jasprit" , null ); System.out.println( "Before Sorting:" ); names.forEach(System.out ::println); names.sort(Comparator.naturalOrder()); System.out.println( "After Sorting:" ); names.forEach(System.out ::println); } |
1 | } |
Here is the output :
Before Sorting:
Gaurav
null
Sachin
Suresh
null
Rohit
Jasprit
null
Exception in thread “main”
java.lang.NullPointerException
at java.base/java.util.Comparators$NaturalOrderComparator.compare(
Comparators.java:52)
at java.base/java.util.Comparators$NaturalOrderComparator.compare(
Comparators.java:47)
at java.base/java.util.TimSort.countRunAndMakeAscending(
TimSort.java:355)
at java.base/java.util.TimSort.sort(
TimSort.java:220)
at java.base/java.util.Arrays.sort(
Arrays.java:1442)
at java.base/java.util.Arrays$ArrayList.sort(
Arrays.java:4426)
at com.blogspot.javasolutionsguide.ComparatorTestWithListOfNamesAndNulls.main(ComparatorTestWithListOfNamesAndNulls.java:12)
As we can see because ,NaturalOrderComparator’s compare method tries to compare two o objects by invoking compareTo on one of the object, we get NullPointerException.
Solving above problem by sorting the list using nullsFirst method
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 | package com.blogspot.javasolutionsguide; import java.util.Arrays; import java.util.List; import java.util.Comparator; /** * @author javasolutionsguide * */ public class ComparatorTestWithNullsFirstForListOfNames { public static void main(String[] args) { List<String> names = Arrays.asList( "Gaurav" , null , "Tendulkar" , "Suresh" , null , "Rohit" , "Jasprit" , null ); System.out.println( "Before Sorting:" ); names.forEach(System.out ::println); names.sort(Comparator.nullsFirst(Comparator.naturalOrder())); System.out.println( "After Sorting:" ); names.forEach(System.out ::println); } |
1 | } |
Here is the output :
Before Sorting:
Gaurav
null
Tendulkar
Suresh
null
Rohit
Jasprit
null
After Sorting:
null
null
null
Gaurav
Jasprit
Rohit
Suresh
Tendulkar
Sorting a list of custom objects without nulls
We will create an Employee class, which will be a simple POJO as below :
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 | package com.blogspot.javasolutionsguide; public class Employee { private int id; private String name; private String department; public Employee( int id, String name, String department) { super (); this .id = id; this .name = name; this .department = department; } public int getId() { return id; |
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 | } public String getName() { return name; } public String getDepartment() { return department; } @Override public String toString() { return "Employee [id=" + id + ", name=" + name + ", department=" + department + "]" ; } } |
And here is our test class :
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 | package com.blogspot.javasolutionsguide; import java.util.Arrays; import java.util.Comparator; import java.util.List; public class ComparatorTestWithListOfEmployeesWithoutNulls { public static void main(String[] args) { List<Employee> employees = Arrays.asList( new Employee( 1 , "Gaurav" , "IT" ), new Employee( 1 , "Tendulkar" , "Admin" ), new Employee( 1 , "Suresh" , "IT" ), new Employee( 1 , "Rohit" , "Admin" ), new Employee( 1 , "Bumrah" , "Admin" )); System.out.println( "Before Sorting:" ); employees.forEach(System.out ::println); System.out.println( "After Sorting:" ); employees.sort(Comparator.comparing(Employee :: getName)); employees.forEach(System.out::println); |
1 | } |
Here is the output :
Before Sorting:
Employee [id=1, name=Gaurav, department=IT]
Employee [id=1, name=Tendulkar, department=Admin]
Employee [id=1, name=Suresh, department=IT]
Employee [id=1, name=Rohit, department=Admin]
Employee [id=1, name=Bumrah, department=Admin]
After Sorting:
Employee [id=1, name=Bumrah, department=Admin]
Employee [id=1, name=Gaurav, department=IT]
Employee [id=1, name=Rohit, department=Admin]
Employee [id=1, name=Suresh, department=IT]
Employee [id=1, name=Tendulkar, department=Admin]
Sorting a list of custom objects with nulls without using nullsFirst
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 | package com.blogspot.javasolutionsguide; import java.util.Arrays; import java.util.Comparator; import java.util.List; public class ComparatorTestWithListOfEmployeesWithNulls { public static void main(String[] args) { List<Employee> employees = Arrays.asList( new Employee( 1 , "Gaurav" , "IT" ), null , new Employee( 1 , "Tendulkar" , "Admin" ), new Employee( 1 , "Suresh" , "IT" ), |
1 2 3 4 5 6 7 | null , new Employee( 1 , "Rohit" , "Admin" ), new Employee( 1 , "Bumrah" , "Admin" ), null ); employees.sort(Comparator.comparing(Employee::getName)); employees.forEach(System.out::println); |
1 | } |
1 | } |
Here is the output :
Before Sorting:
Employee [id=1, name=Gaurav, department=IT]
null
Employee [id=1, name=Tendulkar, department=Admin]
Employee [id=1, name=Suresh, department=IT]
null
Employee [id=1, name=Rohit, department=Admin]
Employee [id=1, name=Bumrah, department=Admin]
null
Exception in thread “main”
java.lang.NullPointerException
at java.base/java.util.Comparator.lambda$comparing$77a9974f$1(
Comparator.java:469)
at java.base/java.util.TimSort.countRunAndMakeAscending(
TimSort.java:355)
at java.base/java.util.TimSort.sort(
TimSort.java:220)
at java.base/java.util.Arrays.sort(
Arrays.java:1442)
at java.base/java.util.Arrays$ArrayList.sort(
Arrays.java:4426)
at com.blogspot.javasolutionsguide.ComparatorTestWithListOfEmployeesWithNulls.main(ComparatorTestWithListOfEmployeesWithNulls.java:19)
Solving above problem by sorting the list using nullsFirst method
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 | package com.blogspot.javasolutionsguide; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; public class ComparatorTestWithListOfEmployeesWithNullsAndNullsFirst { public static void main(String[] args) { List<Employee> employees = Arrays.asList( new Employee( 1 , "Gaurav" , "IT" ), null , new Employee( 1 , "Tendulkar" , "Admin" ), new Employee( 1 , "Suresh" , "IT" ), |
1 2 3 4 5 6 7 8 | null , new Employee( 1 , "Rohit" , "Admin" ), new Employee( 1 , "Bumrah" , "Admin" ), null ); Collections.sort(employees ,Comparator.nullsFirst((emp1 ,emp2) -> emp1.getName().compareToIgnoreCase(emp2.getName()))); employees.forEach(System.out::println); } } |
Here is the output :
null
null
null
Employee [id=1, name=Bumrah, department=Admin]
Employee [id=1, name=Gaurav, department=IT]
Employee [id=1, name=Rohit, department=Admin]
Employee [id=1, name=Suresh, department=IT]
Employee [id=1, name=Tendulkar, department=Admin]
Sorting the list having employee with name as null
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | package com.blogspot.javasolutionsguide; import java.util.Arrays; import java.util.Comparator; import java.util.List; public class ComparatorTestWithListOfEmployeesWithNullNamesAndNullsFirst { public static void main(String[] args) { List<Employee> employees = Arrays.asList( new Employee( 1 , "Gaurav" , "IT" ), new Employee( 1 , "Tendulkar" , "Admin" ), new Employee( 1 , null , "IT" ), new Employee( 1 , "Rohit" , "Admin" ), new Employee( 1 , "Bumrah" , "Admin" )); System.out.println( "Before Sorting:" ); employees.forEach(System.out ::println); employees.sort(Comparator.comparing(Employee::getName,Comparator.nullsFirst(Comparator.naturalOrder()))); System.out.println( "After Sorting:" ); employees.forEach(System.out::println); } } |
Here is the output :
Before Sorting:
Employee [id=1, name=Gaurav, department=IT]
Employee [id=1, name=Tendulkar, department=Admin]
Employee [id=1, name=null, department=IT]
Employee [id=1, name=Rohit, department=Admin]
Employee [id=1, name=Bumrah, department=Admin]
After Sorting:
Employee [id=1, name=null, department=IT]
Employee [id=1, name=Bumrah, department=Admin]
Employee [id=1, name=Gaurav, department=IT]
Employee [id=1, name=Rohit, department=Admin]
Employee [id=1, name=Tendulkar, department=Admin]
Summary
When we have list of elements where few elements are null and we want these nulls to be treated as the smallest elements in the list, we can use nullsFirst method of Comparator interface, which does following :
Returns a null-friendly comparator that considers null to be less than non null.
– When both objects are null, they are considered equal.
– When both are non null, the specified comparator, which is passed to nullsFirst method as parameter, is used to determined the sort order
– When the specified comparator is null, then the returned comparator consider all non null values to be equal.
Thanks for reading. If you liked the post, you can share it and can subscribe to this blog for more such posts.
Published on Java Code Geeks with permission by Gaurav Bhardwaj, partner at our JCG program. See the original article here: Sorting a List having null values with Comparator’s nullsFirst Opinions expressed by Java Code Geeks contributors are their own. |