The different ways to sort Collections in Java

Let’s say you have an Employee class with attributes like name , age , rating etc.

You want to create a number of employees and sort them all by name.

How to do this in Java?

You make the Employee class implement Comparable interface which has a method compareTo().

The Employee class needs to implement this method. Inside the method you can compare the name of the current instance with the name of the employee instance passed as a parameter to the compareTo() method. Like this :

@Override
	public int compareTo(Employee o) {
		
		return this.name.compareTo(o.getName());
	}

And then you can invoke the method sort() on Collections like this:

		Collections.sort(employees);

The above code sorts all employees based on the name.

It works fine if you want to sort based on a single field.

What if you want to sort based on rating of an employee?

You can use Comparator interface for this. Instead of changing the Employee class , create a class which implements Comparator interface and implement the compare() method of the interface. It takes two arguments which can be compared against each other :

package comparator.traditional;

import java.util.Comparator;

public class RatingComparator implements Comparator<Employee> {

	@Override
	public int compare(Employee emp1, Employee emp2) {

		return emp1.getRating() - emp2.getRating();
	}

}

To sort the employees using the above comparator , pass a new instance of this comparator to Collections.sort() method as a parameter:

	Collections.sort(employees, new RatingComparator());

And then came Java 8 with a slew of new features.

Remember Comparator is a functional interface , an interface with a single method. And a functional interface can be represented by a lamda expression.

And hence instead of creating a new class (RatingComparator) you can directly pass the implementation of the method compare() as a lamda expression to Collections.sort() method :

Collections.sort(employees, (emp1, emp2) -> {
			return emp1.getRating() - emp2.getRating();
		});

Less code , same output!

To further optimize this , Java 8 also introduced static methods. The Comparator interface has a static method named comparing() which does the comparing for given two fields.

The above code can then be replaced using the below:

Collections.sort(employees, Comparator.comparing((employee) -> employee.getRating()));

Further in the above code the expression (employee) -> employee.getRating() can be replaced by the method reference Employee::getRating():

Collections.sort(employees, Comparator.comparing(Employee::getRating));

If you want to sort in reversed order , Java 8 came up with default methods in interface and the Comparator interface provides the default method reversed() which sorts the collection in reverse order. To sort the above employee list based on rating in descending order , do this :

Collections.sort(employees, Comparator.comparing(Employee::getRating).reversed());

Say , two employees have the same rating and if the rating is the same, you want to compare the employees based on their experience, you can then use another default method thenComparing() provided since Java 8 to achieve this:

Collections.sort(employees, Comparator.comparing(Employee::getRating).thenComparing(Comparator.comparing(Employee::getExperience)));

thenComparing() takes a comparator instance as a parameter. The above code sorts the employees based on their rating and if their ratings are equal then sorts them based on their experience.

Java 8 has made sorting less verbose than it was before!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s