Comparators and Applications in JAVA
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);
}
}
Subscribe to my newsletter
Read articles from Paras kaushik directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Paras kaushik
Paras kaushik
Hello, I'm Paras Kaushik! ๐ I'm a dedicated software engineer based in India, specializing in C++ and proficient in the MERN stack. ๐ค Interested in collaborating on innovative projects that require my technical expertise. ๐ฌ Passionate about participating in discussions related to software architecture and best practices. ๐ง Feel free to reach out to me via email: [paraskaushik12@gmail.com] ๐ Connect with me on LinkedIn: [https://www.linkedin.com/in/the-paras-kaushik/]