Introduce Java Advanced Sorting (Comparator and Comparable) and give examples
In Java, sorting collections of objects can be accomplished using two primary interfaces: Comparable
and Comparator
. Both interfaces allow you to define the order in which objects are sorted, but they do so in different ways.
The Comparable
interface is used to define a natural ordering for the objects of a class. A class that implements Comparable
must override the compareTo
method, which compares the current object with another object of the same type.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class Person implements Comparable<Person> {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public int compareTo(Person other) {
return this.age - other.age; // Sort by age
}
@Override
public String toString() {
return name + " (" + age + ")";
}
}
public class ComparableExample {
public static void main(String[] args) {
List<Person> people = new ArrayList<>();
people.add(new Person("Alice", 30));
people.add(new Person("Bob", 25));
people.add(new Person("Charlie", 35));
Collections.sort(people); // Sorts using the compareTo method
System.out.println(people);
}
}
Output:
[Bob (25), Alice (30), Charlie (35)]
The Comparator
interface is used to define an external ordering for objects. This is useful when you want to sort objects in different ways without modifying the class itself. You can create multiple Comparator
implementations for the same class.
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return name + " (" + age + ")";
}
}
public class ComparatorExample {
public static void main(String[] args) {
List<Person> people = new ArrayList<>();
people.add(new Person("Alice", 30));
people.add(new Person("Bob", 25));
people.add(new Person("Charlie", 35));
// Sort by name
Collections.sort(people, new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
return p1.getName().compareTo(p2.getName());
}
});
System.out.println("Sorted by name: " + people);
// Sort by age
Collections.sort(people, new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
return p1.getAge() - p2.getAge();
}
});
System.out.println("Sorted by age: " + people);
}
}
Output:
Sorted by name: [Alice (30), Bob (25), Charlie (35)]
Sorted by age: [Bob (25), Alice (30), Charlie (35)]
Since Java 8, you can use lambda expressions to simplify the creation of Comparator
instances.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return name + " (" + age + ")";
}
}
public class LambdaComparatorExample {
public static void main(String[] args) {
List<Person> people = new ArrayList<>();
people.add(new Person("Alice", 30));
people.add(new Person("Bob", 25));
people.add(new Person("Charlie", 35));
// Sort by name using lambda
Collections.sort(people, (p1, p2) -> p1.getName().compareTo(p2.getName()));
System.out.println("Sorted by name: " + people);
// Sort by age using lambda
Collections.sort(people, (p1, p2) -> Integer.compare(p1.getAge(), p2.getAge()));
System.out.println("Sorted by age: " + people);
}
}
Output:
Sorted by name: [Alice (30), Bob (25), Charlie (35)]
Sorted by age: [Bob (25), Alice (30), Charlie (35)]
Comparator
instances.These tools provide flexibility in sorting collections of objects in Java.