Comparators and Applications in JAVA

ยท

5 min read

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

  1. Using Anonymous Classes
Comparator<Type> comparator = new Comparator<Type>() {
    @Override
    public int compare(Type o1, Type o2) {
        // comparison logic
        return comparisonResult;
    }
};
  1. 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);
    }
}
ย