Understanding Comparator
A Comparator
is an functional interface used to order objects of a user-defined class. It provides a method compare(T o1, T o2)
that must be overridden to define the sorting logic.
Syntax
- Using Anonymous Classes
Comparator<Type> comparator = new Comparator<Type>() {
@Override
public int compare(Type o1, Type o2) {
// comparison logic
return comparisonResult;
}
};
- Using Lambda Expressions
Comparator<Type> comparator = (Type o1, Type o2) -> {
// comparison logic
return comparisonResult;
};
Example: Sorting by Age and then by Name
import java.util.*;
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return name + ": " + age;
}
}
public class Main {
public static void main(String[] args) {
List<Person> people = new ArrayList<>(Arrays.asList(
new Person("Alice", 30),
new Person("Bob", 30),
new Person("Charlie", 25)
));
// Custom order: first by age, then by name
Comparator<Person> comparator = new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
if (p1.age != p2.age) {
return Integer.compare(p1.age, p2.age);
} else {
return p1.name.compareTo(p2.name);
}
}
};
Collections.sort(people, comparator);
Collections.sort(people,(p1,p2)->
Integer.compare(p1.age, p2.age));//Ascending
Collections.sort(people,(p1,p2)->
Integer.compare(p2.age, p1.age));//Descending
//First by name then age
Collections.sort(people,(p1,p2)->
((p1.name==p2.name) ?
Integer.compare(p1.age, p2.age)
:p1.name.compareTo(p2.name)));//Descending
System.out.println(people);
}
}
Sorting Using Lambda Expressions
1. ArrayList
import java.util.*;
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return name + ": " + age;
}
}
public class Main {
public static void main(String[] args) {
List<Person> people = new ArrayList<>(Arrays.asList(
new Person("Alice", 30),
new Person("Bob", 25),
new Person("Charlie", 35)
));
// Sort by age in ascending order
people.sort((Person p1, Person p2) ->
Integer.compare(p1.age, p2.age));
System.out.println("Sorted by age (ascending): " + people);
// Sort by age in descending order
people.sort((Person p1, Person p2) ->
Integer.compare(p2.age, p1.age));
System.out.println("Sorted by age (descending): " + people);
// Custom order: first by age, then by name
people.sort((Person p1, Person p2) -> {
int ageComparison = Integer.compare(p1.age, p2.age);
if (ageComparison != 0) {
return ageComparison;
}
return p1.name.compareTo(p2.name);
});
System.out.println("Custom order (by age then name): " + people);
}
}
2. LinkedList
import java.util.*;
public class Main {
public static void main(String[] args) {
LinkedList<Person> people = new LinkedList<>(Arrays.asList(
new Person("Alice", 30),
new Person("Bob", 25),
new Person("Charlie", 35)
));
// Sort by age in ascending order
people.sort((Person p1, Person p2) -> Integer.compare(p1.age, p2.age));
System.out.println("Sorted by age (ascending): " + people);
// Sort by age in descending order
people.sort((Person p1, Person p2) -> Integer.compare(p2.age, p1.age));
System.out.println("Sorted by age (descending): " + people);
// Custom order: first by age, then by name
people.sort((Person p1, Person p2) -> {
int ageComparison = Integer.compare(p1.age, p2.age);
if (ageComparison != 0) {
return ageComparison;
}
return p1.name.compareTo(p2.name);
});
System.out.println("Custom order (by age then name): " + people);
}
}
3. PriorityQueue
import java.util.*;
public class Main {
public static void main(String[] args) {
PriorityQueue<Person> queue =
new PriorityQueue<>
((Person p1, Person p2) -> Integer.compare(p1.age, p2.age));
PriorityQueue<Person> queue =
new PriorityQueue<>
((Person p1, Person p2) -> p1.name.compareTo(p2.name));
queue.add(new Person("Alice", 30));
queue.add(new Person("Bob", 25));
queue.add(new Person("Charlie", 35));
while (!queue.isEmpty()) {
System.out.println(queue.poll());
}
}
}
4. Deque and ArrayDeque
import java.util.*;
public class Main {
public static void main(String[] args) {
Deque<Person> deque = new ArrayDeque<>(Arrays.asList(
new Person("Alice", 30),
new Person("Bob", 25),
new Person("Charlie", 35)
));
// will have to convert to list to run ops on it
// the constructor of list takes ANY collection to init from
List<Person> sortedList = new ArrayList<>(deque);
// Sort by age in ascending order
sortedList.sort((Person p1, Person p2) -> Integer.compare(p1.age, p2.age));
System.out.println("Sorted by age (ascending): " + sortedList);
// Sort by age in descending order
sortedList.sort((Person p1, Person p2) -> Integer.compare(p2.age, p1.age));
System.out.println("Sorted by age (descending): " + sortedList);
// Custom order: first by age, then by name
sortedList.sort((Person p1, Person p2) -> {
int ageComparison = Integer.compare(p1.age, p2.age);
if (ageComparison != 0) {
return ageComparison;
}
return p1.name.compareTo(p2.name);
});
System.out.println("Custom order (by age then name): " + sortedList);
}
}
5. HashSet and TreeSet
For HashSet
, we need to convert it to a List
for sorting, and for TreeSet
, we can use a Comparator
in the constructor:
import java.util.*;
public class Main {
public static void main(String[] args) {
Set<Person> peopleSet = new HashSet<>(Arrays.asList(
new Person("Alice", 30),
new Person("Bob", 25),
new Person("Charlie", 35)
));
// Convert to List and sort by age in ascending order
List<Person> sortedList = new ArrayList<>(peopleSet);
sortedList.sort((Person p1, Person p2) -> Integer.compare(p1.age, p2.age));
System.out.println("HashSet sorted by age (ascending): " + sortedList);
// TreeSet with custom comparator (sort by age in descending order)
TreeSet<Person> sortedSet = new TreeSet<>((Person p1, Person p2) -> Integer.compare(p2.age, p1.age));
sortedSet.addAll(peopleSet);
System.out.println("TreeSet sorted by age (descending): " + sortedSet);
}
}
6. HashMap and TreeMap
Sorting a HashMap
by values:
javaCopy codeimport java.util.*;
public class Main {
public static void main(String[] args) {
Map<String, Person> peopleMap = new HashMap<>();
peopleMap.put("a", new Person("Alice", 30));
peopleMap.put("b", new Person("Bob", 25));
peopleMap.put("c", new Person("Charlie", 35));
// TreeMap with custom comparator for values (sort by age in ascending order)
TreeMap<String, Person> sortedByAgeMap = new TreeMap<>((String k1, String k2) -> {
return Integer.compare(peopleMap.get(k1).age, peopleMap.get(k2).age);
});
sortedByAgeMap.putAll(peopleMap);
System.out.println("TreeMap sorted by age (ascending): " + sortedByAgeMap);
// TreeMap with custom comparator for values (sort by age in descending order)
TreeMap<String, Person> sortedByAgeDescMap = new TreeMap<>((String k1, String k2) -> {
return Integer.compare(peopleMap.get(k2).age, peopleMap.get(k1).age);
});
sortedByAgeDescMap.putAll(peopleMap);
System.out.println("TreeMap sorted by age (descending): " + sortedByAgeDescMap);
}
}
ย