Sort an ArrayList of Objects with Comparable and Comparator

In this tutorial, we'll see how to sort an ArrayList that contains objects using the two interfaces java.lang.Comparable and java.util.Comparator. If your program requires sorting an ArrayList of String or Integer, it's best to check out these two articles:

- Sort a String or Integer ArrayList
- Sort an ArrayList in descending order

The Comparable interface is used when you want to sort a list of objects by comparing two objects with the predefined method object1.compareTo(object2).

Sort an ArrayList using Comparable

First, let's see the sorting result of an arraylist of objects without implementing the Comparable interface.

Let's create a Employe.java class:

public class Employee {

private String name;
private int age;
private long salary;

public String getName() {
return name;
}

public int getAge() {
return age;
}

public long getSalary() {
return salary;
}

public Employee(String name, int age, int salary) {
this.name = name;
this.age = age;
this.salary = salary;
}

@Override
//this method displays employee information
public String toString() {
return "[name=" + this.name + ", age=" + this.age + ", salary=" +
this.salary + "]";
}
}
We want to create a list of ArrayList< Employee>:

import java.util.ArrayList; 
import java.util.Collections;

public class ArrayListComparable {

public static void main(String[] args) {
ArrayList< Employee> arraylist = new ArrayList< Employee> ();
arraylist.add(new Employe("mateo", 32, 20000));
arraylist.add(new Employe("katia", 26, 10000));
arraylist.add(new Employe("aline", 30, 40000));
arraylist.add(new Employe("salim", 28, 35000));

System.out.println("Ordered list of employees:\n"+Collections.sort(arraylist));
}
}
Calling the Collections.sort() cause a problem because it is done on an ArrayList of objects that does not work unless you use both the Comparable and Comparator interfaces. A compilation error appears:

Exception in thread "main" java.lang.Error: Unresolved compilation problems: 
The operator + is undefined for the argument type(s) String, void
Bound mismatch: The generic method sort(List) of type Collections is not applicable for the arguments (ArrayList). The inferred type Employe is not a valid substitute for the bounded parameter >

at ArrayListComparable.main(ArrayListComparable.java:14)

Now you must have understood the importance of these two interfaces.

Let's say we want to sort the list by the property: employee's salary. This can be done by implementing the Comparable interface, and then java does an automatic comparison with the compareTo()declared Override.

After implementing the Comparable interface in the Employe.java class, the result is as follows:

public class Employe implements Comparable< Employee> {

private String name;
private int age;
private long salary;

public String getName() {
return name;
}

public int getAge() {
return age;
}

public long getSalary() {
return salary;
}

public Employee(String name, int age, int salary) {
this.name = name;
this.age = age;
this.salary = salary;
}

@Override
//this method displays employee information
public String toString() {
return "[name=" + this.name + ", age=" + this.age + ", salary=" +
this.salary + "]";
}

@Override
public int compareTo(Employee emp) {
//sort employees by age in order croiddant
//retroune a negative, zero, or positive integer if the age
//of that employee is less than, equal to, or greater than the object compared with
return (this.age - emp.age);
}
}
Now we have the right to call the method Collections.sort():

import java.util.ArrayList; 
import java.util.Collections;

public class ArrayListComparable {

public static void main(String[] args) {
ArrayList< Employee> arraylist = new ArrayList< Employee> ();

arraylist.add(new Employe("mateo", 32, 20000));
arraylist.add(new Employe("katia", 26, 10000));
arraylist.add(new Employe("aline", 30, 40000));
arraylist.add(new Employe("salim", 28, 35000));

Collections.sort(arraylist);

System.out.println("ordered list of employees by age:\n");
for(Employee e:arraylist)
System.out.println(e);
}
}
When we run this piece of code we will have the following result:

ordered list of employees by age:

[name=katia, age=26, salary=10000]
[name=salim, age=28, salary=35000]
[name=aline, age=30, salary=40000]
[name=mateo, age=32, salary=20000]

Sort an ArrayList using Comparator

As you can see, the list of employees above is sorted in ascending order. but why use the Comparator interface then? Because there may be situations where the sorting is based on several parameters unlike Comparable. For example, we want the sorting of employees to be based on name, age, and salary.

The compare(Object o1, Object o2) of the Comparator interface takes two objects. In our example, it must be implemented three times (name, age, and salary) so that it returns a negative integer if the first argument is smaller than the second and zero if they are equal and a positive integer if the first argument is larger than the second.

import java.util.Comparator; 

public class Employee {

private String name;
private int age;
private long salary;

public String getNom() {
return name;
}

public int getAge() {
return age;
}

public long getSalary() {
return salary;
}

public Employee(String name, int age, int salary) {
this.name = name;
this.age = age;
this.salary = salary;
}

@Override
//this method displays employee information
public String toString() {
return "[name=" + this.name + ", age=" + this.age + ", salary=" +
this.salary + "]";
}

/*
* Comparator for sorting employees by name
*/
public static Comparator< Employee> ComparatorName = new Comparator< Employee> () {

@Override
public int compare(Employee e1, Employee e2) {
return e1.getName().compareTo(e2.getName());
}
};
/*
* Comparator for sorting employees by age
*/
public static Comparator< Employee> ComparatorAge = new Comparator< Employee> () {

@Override
public int compare(Employee e1, Employee e2) {
return (int) (e1.getAge() - e2.getAge());
}
};
/*
* Comparator for sorting employees by salary
*/
public static Comparator< Employee> ComparatorSalary = new Comparator< Employee> () {

@Override
public int compare(Employee e1, Employee e2) {
return (int) (e1.getSalary() - e2.getSalary());
}
};
}
The test class main:

import java.util.ArrayList; 
import java.util.Collections;

public class main{

public static void main(String[] args) {
ArrayList< Employee> arraylist = new ArrayList< Employee> ();

arraylist.add(new Employe("mateo", 32, 20000));
arraylist.add(new Employe("katia", 26, 10000));
arraylist.add(new Employe("aline", 30, 40000));
arraylist.add(new Employe("salim", 28, 35000));

//sort by name
Collections.sort(arraylist, Employee.ComparatorName);

System.out.println("ordered list of employees by name:");
for(Employee e:arraylist)
System.out.println(e);

//sort by age
Collections.sort(arraylist, Employee.ComparatorAge);

System.out.println("ordered list of employees by age:");
for(Employee e:arraylist)
System.out.println(e);

//sort by salary
Collections.sort(arraylist, Employee.ComparatorSalary);

System.out.println("ordered list of employees by salary:");
for(Employee e:arraylist)
System.out.println(e);
}
}
The execution of this code gives:

ordered list of employees by name:
[name=aline, age=30, salary=40000]
[name=katia, age=26, salary=10000]
[name=mateo, age=32, salary=20000]
[name=Salim, age=28, salary=35000]
ordered list of employees by age:
[name=katia, age=26, salary=10000]
[name=salim, age=28, salary=35000]
[name=aline, age=30, salary=40000]
[name=mateo, age=32, salary=20000]
ordered list of employees by salary:
[name=katia, age=26, salary=10000]
[name=mateo, age=32, salary=20000]
[name=salim, age=28, salary=35000]
[name=aline, age=30, salary=40000]