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("Fola", 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), Fola(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("Fola", 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); // [Fola(85), Jamal(78), Zain(92)]
students.sort(Comparator.comparingInt((Student s) -> s.grade).reversed());
System.out.println(students); // [Zain(92), Fola(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", "Fola"));
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: Fola]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)
At a glance
- Purpose
- General-purpose application development
- File extension
- .java
- Runs in
- Java Virtual Machine
- Usually used with
- JDK and Java libraries
Specifications & further reading
Related Java documentation
ArrayList
ArrayList is a resizable array implementation of the List interface, part of java.util. Unlike a plain array, an ArrayList automatically grows as elements are added, and it provides a rich set of methods for adding, removing, searching, and iterating. Since generics require object types, an ArrayList of primitives (like int) actually stores their wrapper class (Integer) via autoboxing.LinkedList
LinkedList is a doubly-linked list implementation of both the List and Deque interfaces. Unlike ArrayList, it stores elements as individual nodes linked to their neighbors, which makes inserting and removing elements at the beginning or middle much faster, at the cost of slower random access by index. Because it implements Deque, LinkedList can also be used directly as a stack or queue.HashMap
HashMap stores data as key-value pairs, offering constant-time (average case) lookup, insertion, and deletion by key, backed by a hash table. Keys must be unique - adding a value with an existing key overwrites the previous value. HashMap does not guarantee any particular ordering of its entries, unlike LinkedHashMap (which preserves insertion order) or TreeMap (which keeps keys sorted).HashSet
HashSet is a collection that stores unique elements with no guaranteed ordering, backed by a HashMap internally. Adding a duplicate element has no effect, since HashSet automatically enforces uniqueness. It provides constant-time (average case) performance for adding, removing, and checking membership, making it ideal for deduplication and fast lookups.
ArrayList is a resizable array implementation of the List interface, part of java.util. Unlike a plain array, an ArrayList automatically grows as elements are added, and it provides a rich set of methods for adding, removing, searching, and iterating. Since generics require object types, an ArrayList of primitives (like int) actually stores their wrapper class (Integer) via autoboxing.LinkedList
LinkedList is a doubly-linked list implementation of both the List and Deque interfaces. Unlike ArrayList, it stores elements as individual nodes linked to their neighbors, which makes inserting and removing elements at the beginning or middle much faster, at the cost of slower random access by index. Because it implements Deque, LinkedList can also be used directly as a stack or queue.HashMap
HashMap stores data as key-value pairs, offering constant-time (average case) lookup, insertion, and deletion by key, backed by a hash table. Keys must be unique - adding a value with an existing key overwrites the previous value. HashMap does not guarantee any particular ordering of its entries, unlike LinkedHashMap (which preserves insertion order) or TreeMap (which keeps keys sorted).HashSet
HashSet is a collection that stores unique elements with no guaranteed ordering, backed by a HashMap internally. Adding a duplicate element has no effect, since HashSet automatically enforces uniqueness. It provides constant-time (average case) performance for adding, removing, and checking membership, making it ideal for deduplication and fast lookups.