What is the Difference Between Comparable and Comparator in Java?
Both are used for sorting, but Comparable defines natural ordering within the class, while Comparator defines custom ordering externally.
1. Comparable (Natural Ordering)
import java.util.*;
class Student implements Comparable {
int id;
String name;
int age;
Student(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
@Override
public int compareTo(Student other) {
// Natural ordering by id
return Integer.compare(this.id, other.id);
}
@Override
public String toString() {
return id + ":" + name + "(" + age + ")";
}
}
public class ComparableExample {
public static void main(String[] args) {
List students = new ArrayList<>();
students.add(new Student(103, "Charlie", 22));
students.add(new Student(101, "Alice", 20));
students.add(new Student(102, "Bob", 21));
System.out.println("Before sort: " + students);
Collections.sort(students); // Uses compareTo
System.out.println("After sort (by id): " + students);
// Comparable only provides ONE natural ordering
// Cannot sort by name or age without modifying the class
}
}
2. Comparator (Custom Ordering)
class Employee {
int id;
String name;
double salary;
Employee(int id, String name, double salary) {
this.id = id;
this.name = name;
this.salary = salary;
}
@Override
public String toString() {
return id + ":" + name + "($" + salary + ")";
}
}
public class ComparatorExample {
public static void main(String[] args) {
List employees = new ArrayList<>();
employees.add(new Employee(103, "Charlie", 55000));
employees.add(new Employee(101, "Alice", 62000));
employees.add(new Employee(102, "Bob", 58000));
employees.add(new Employee(104, "Alice", 60000));
// Sort by name using anonymous class
Comparator nameComparator = new Comparator() {
@Override
public int compare(Employee e1, Employee e2) {
return e1.name.compareTo(e2.name);
}
};
Collections.sort(employees, nameComparator);
System.out.println("Sort by name: " + employees);
// Sort by salary using Lambda (Java 8+)
Comparator salaryComparator = (e1, e2) ->
Double.compare(e1.salary, e2.salary);
Collections.sort(employees, salaryComparator);
System.out.println("Sort by salary: " + employees);
// Sort by salary descending
Collections.sort(employees, (e1, e2) ->
Double.compare(e2.salary, e1.salary));
System.out.println("Sort by salary desc: " + employees);
}
}
Multiple Comparators and Chaining
public class MultipleComparators {
public static void main(String[] args) {
List employees = Arrays.asList(
new Employee(101, "Alice", 62000),
new Employee(102, "Bob", 58000),
new Employee(103, "Alice", 60000),
new Employee(104, "Charlie", 62000),
new Employee(105, "Alice", 59000)
);
// 1. Sort by name, then by salary using Comparator.comparing
Comparator byNameThenSalary =
Comparator.comparing((Employee e) -> e.name)
.thenComparing(e -> e.salary);
employees.sort(byNameThenSalary);
System.out.println("By name then salary: " + employees);
// 2. Sort by name, then by id descending
Comparator byNameThenIdDesc =
Comparator.comparing((Employee e) -> e.name)
.thenComparing((e1, e2) -> Integer.compare(e2.id, e1.id));
employees.sort(byNameThenIdDesc);
System.out.println("By name then id desc: " + employees);
// 3. Sort by salary descending using comparing with reversed
Comparator bySalaryDesc =
Comparator.comparing((Employee e) -> e.salary).reversed();
employees.sort(bySalaryDesc);
System.out.println("By salary desc: " + employees);
// 4. Null handling
employees.add(null);
Comparator nullSafe =
Comparator.nullsLast(Comparator.comparing(e -> e.name));
employees.sort(nullSafe);
System.out.println("Null-safe sort: " + employees);
}
}
Java 8 Comparator Improvements
import java.util.Comparator;
class Product {
String name;
double price;
int rating;
Product(String name, double price, int rating) {
this.name = name;
this.price = price;
this.rating = rating;
}
String getName() { return name; }
double getPrice() { return price; }
int getRating() { return rating; }
@Override
public String toString() {
return name + "($" + price + ", rating:" + rating + ")";
}
}
public class Java8Comparator {
public static void main(String[] args) {
List products = Arrays.asList(
new Product("Laptop", 1200.00, 5),
new Product("Mouse", 25.99, 4),
new Product("Keyboard", 75.50, 5),
new Product("Monitor", 350.00, 4),
new Product("Laptop", 1100.00, 4)
);
// Method reference
Comparator byPrice = Comparator.comparing(Product::getPrice);
products.sort(byPrice);
System.out.println("By price: " + products);
// Chain comparators
products.sort(Comparator.comparing(Product::getName)
.thenComparing(Product::getPrice));
System.out.println("By name then price: " + products);
// Reverse order
products.sort(Comparator.comparing(Product::getPrice).reversed());
System.out.println("By price desc: " + products);
// Multiple fields with different order
products.sort(Comparator.comparing(Product::getRating).reversed()
.thenComparing(Product::getPrice));
System.out.println("By rating desc then price: " + products);
// Natural order for Comparable types
List numbers = Arrays.asList(5, 2, 8, 1, 9, 3);
numbers.sort(Comparator.naturalOrder());
System.out.println("Natural order: " + numbers);
numbers.sort(Comparator.reverseOrder());
System.out.println("Reverse order: " + numbers);
// Comparing with custom comparison
List strings = Arrays.asList("apple", "Banana", "cherry", "Date");
strings.sort(String.CASE_INSENSITIVE_ORDER);
System.out.println("Case insensitive: " + strings);
}
}
Comparison Table
| Feature | Comparable | Comparator |
|---|---|---|
| Purpose | Natural/default sorting order | Custom sorting order |
| Method to implement | compareTo() | compare() |
| Package | java.lang | java.util | Modifies class | Yes (needs to modify the class) | No (external to class) |
| Multiple sorting options | Only one natural ordering | Multiple custom comparators |
| Sorting logic | Inside the class | Separate class or lambda |
| Used by | Collections.sort(list) | Collections.sort(list, comparator) |
Practical Examples
public class PracticalExamples {
public static void main(String[] args) {
// Example 1: Sorting Strings (String implements Comparable)
List words = Arrays.asList("banana", "apple", "cherry", "date");
Collections.sort(words); // Natural order (alphabetical)
System.out.println("Sorted strings: " + words);
// Example 2: Custom sorting by length
words.sort(Comparator.comparingInt(String::length));
System.out.println("By length: " + words);
// Example 3: Sorting with multiple criteria
List names = Arrays.asList("John", "Alice", "Bob", "Johnny", "Al");
names.sort(Comparator.comparingInt(String::length)
.thenComparing(Comparator.naturalOrder()));
System.out.println("By length then alphabetically: " + names);
// Example 4: Reverse comparator
List scores = Arrays.asList(95, 87, 92, 100, 88);
scores.sort(Comparator.reverseOrder());
System.out.println("Highest scores first: " + scores);
// Example 5: Using Comparator.comparing for objects
List inventory = Arrays.asList(
new Product("Apple", 0.50, 4),
new Product("Banana", 0.30, 5),
new Product("Orange", 0.60, 4)
);
// Sort by rating descending, then price ascending
inventory.sort(Comparator.comparing(Product::getRating).reversed()
.thenComparing(Product::getPrice));
System.out.println("Best rated first, cheapest among same rating: " + inventory);
}
}
Master Java sorting with Online Learner!
0
likes
Your Feedback
Help us improve by sharing your thoughts
Online Learner helps developers master programming, database concepts, interview preparation, and real-world implementation through structured learning paths.
Quick Links
© 2023 - 2026 OnlineLearner.in | All Rights Reserved.
