Syntax
class X implements Comparable<X> { public int compareTo(X other) { } }Examples
Implementing Comparable
Defining a class's single natural ordering.
class Student implements Comparable<Student> {
String name;
int grade;
Student(String name, int grade) {
this.name = name;
this.grade = grade;
}
@Override
public int compareTo(Student other) {
return this.grade - other.grade; // ascending order by grade
}
@Override
public String toString() {
return name + "(" + grade + ")";
}
}
import java.util.ArrayList;
import java.util.Collections;
ArrayList<Student> students = new ArrayList<>();
students.add(new Student("John", 85));
students.add(new Student("Zain", 92));
students.add(new Student("Jamal", 78));
Collections.sort(students); // uses compareTo() automatically
System.out.println(students); // [Jamal(78), John(85), Zain(92)]Using a Comparator for Custom Order
A Comparator lets you sort the same objects in a different way without changing the class.
import java.util.ArrayList;
import java.util.Comparator;
ArrayList<Student> students = new ArrayList<>();
students.add(new Student("John", 85));
students.add(new Student("Zain", 92));
students.add(new Student("Jamal", 78));
students.sort(Comparator.comparing(s -> s.name)); // sort by name instead
System.out.println(students); // [Jamal(78), John(85), Zain(92)]
students.sort(Comparator.comparingInt((Student s) -> s.grade).reversed());
System.out.println(students); // [Zain(92), John(85), Jamal(78)]Chaining Comparators
Sorting by multiple criteria: primary key first, then a secondary key for ties.
import java.util.ArrayList;
import java.util.Comparator;
class Employee {
String department;
String name;
Employee(String department, String name) {
this.department = department;
this.name = name;
}
public String toString() { return department + ": " + name; }
}
ArrayList<Employee> employees = new ArrayList<>();
employees.add(new Employee("Engineering", "Zain"));
employees.add(new Employee("Sales", "John"));
employees.add(new Employee("Engineering", "Amir"));
employees.sort(
Comparator.comparing((Employee e) -> e.department)
.thenComparing(e -> e.name)
);
System.out.println(employees);
// [Engineering: Amir, Engineering: Zain, Sales: John]Best practices
- Implement Comparable when a class has one obvious, natural ordering (like numbers by value, or dates chronologically)
- Use a Comparator when you need multiple different orderings, or when you cannot modify the class being sorted (like a class from a library)
- Use Comparator.comparing() with method references or lambdas for concise, readable comparator definitions instead of writing compare() by hand
- Chain comparators with .thenComparing() for multi-level sorting (sort by one field, then break ties with another)
Runtime & versions
Java Virtual Machine. Feature availability depends on the language and runtime version used by your project; consult the official reference below.
Java Language Specification