Skip to content

5.11 Self 9.2

Comparator and comparable

Comparable is a logic that define how to compare, use compareTo

public class T implements Comparable<T> {
    @Override
    public int compareTo(T obj);

}

Comparator is a method to make object comparable.

public int compare(Object obj1, Object obj2):

image

For example

This is a normal way to sort integer

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
//List is an interface that extends Collection interface  
//You need a concrete class that implements List
public class main {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(45);
        numbers.add(21);
        numbers.add(67);
        numbers.add(23);

        System.out.println("Before sorting: " + numbers);
        Collections.sort(numbers);
        System.out.println("After sorting: " + numbers);    

    }
}

Now, we want to sort these numbers according to the last digit, then we have two ways

1. Using Comparator

  1. The basic way

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.List;
    //List is an interface that extends Collection interface  
    //You need a concrete class that implements List
    public class main {
    
        static class CompareByLastDigit implements Comparator<Integer> {
            @Override
            public int compare(Integer i, Integer j) {
                if (i % 10 < j % 10)
                    return -1;
                else
                    return 1;
            }
        }
    
        public static void main(String[] args) {
    
            Comparator<Integer> comparator = new CompareByLastDigit();
    
            List<Integer> numbers = new ArrayList<>();
    
            numbers.add(41);
            numbers.add(22);
            numbers.add(60);
            numbers.add(23);
    
            System.out.println("Before sorting: " + numbers);
            Collections.sort(numbers, comparator);
            System.out.println("After sorting: " + numbers);    
    
        }
    }
    
  2. Using anonymous class

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.List;
    //List is an interface that extends Collection interface  
    //You need a concrete class that implements List
    public class main {
        public static void main(String[] args) {
    
            Comparator<Integer> comparator = new Comparator<Integer>() {
            public int compare(Integer i, Integer j) {
                if(i % 10 < j % 10)
                    return -1;
                else
                    return 1;
            }
        };
    
            List<Integer> numbers = new ArrayList<>();
    
            numbers.add(41);
            numbers.add(22);
            numbers.add(60);
            numbers.add(23);
    
            System.out.println("Before sorting: " + numbers);
            Collections.sort(numbers, comparator);
            System.out.println("After sorting: " + numbers);    
    
        }
    }
    
  3. Using lambda expression

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.List;
    //List is an interface that extends Collection interface  
    //You need a concrete class that implements List
    public class main {
        public static void main(String[] args) {
    
            Comparator<Integer> comparator = (Integer i, Integer j) -> i % 10 < j % 10 ? -1 : 1;
    
            List<Integer> numbers = new ArrayList<>();
    
            numbers.add(41);
            numbers.add(22);
            numbers.add(60);
            numbers.add(23);
    
            System.out.println("Before sorting: " + numbers);
            Collections.sort(numbers, comparator);
            System.out.println("After sorting: " + numbers);    
    
        }
    }
    

2. Using Comparable

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
//List is an interface that extends Collection interface  
//You need a concrete class that implements List
public class main {

    static class LastDigitNumber implements Comparable<LastDigitNumber> {
        private int value;
        public LastDigitNumber(int value) { 
            this.value = value; 
        }
        @Override
        public int compareTo(LastDigitNumber other) { 
            return Integer.compare(this.value % 10, other.value % 10); 
        }
        @Override
        public String toString() { 
            return String.valueOf(value); 
        }
    }
    public static void main(String[] args) {
        List<LastDigitNumber> numbers = new ArrayList<>();
        numbers.add(new LastDigitNumber(41));
        numbers.add(new LastDigitNumber(22));
        numbers.add(new LastDigitNumber(60));
        numbers.add(new LastDigitNumber(23));
        System.out.println("Before sorting: " + numbers);
        Collections.sort(numbers);
        System.out.println("After sorting: " + numbers);    
    }
}

Now, we are given a more complex example

We have some students and want to sort students by age

  1. Using comparable

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    //List is an interface that extends Collection interface  
    //You need a concrete class that implements List
    public class main {
    
        static class Student implements Comparable<Student> {
            private String name;
            private int age;
            public Student(String name, int age) {
                this.name = name;
                this.age = age;
            }
            @Override
            public int compareTo(Student other) {
                return Integer.compare(this.age, other.age);
            }
            @Override
            public String toString() {
                return name + "(" + age + ")";
            }
        }
        public static void main(String[] args) {
            List<Student> students = new ArrayList<>();
            students.add(new Student("Alice", 21));
            students.add(new Student("Bob", 19));
            students.add(new Student("Charlie", 22));
            students.add(new Student("Dave", 20));
            System.out.println("Before sorting: " + students);
            Collections.sort(students);
            System.out.println("After sorting: " + students);    
        }
    }
    
  2. Using Comparator

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    import java.util.Comparator;
    //List is an interface that extends Collection interface  
    //You need a concrete class that implements List
    public class main {
    
        static class Student {
            public String name;
            public int age;
            public Student(String name, int age) {
                this.name = name;
                this.age = age;
            }
            @Override
            public String toString() {
                return name + "(" + age + ")";
            }
        }
        public static void main(String[] args) {
            List<Student> students = new ArrayList<>();
            Comparator<Student> comparator = (Student i, Student j) -> i.age < j.age ? -1 : 1;
            students.add(new Student("Alice", 21));
            students.add(new Student("Bob", 19));
            students.add(new Student("Charlie", 22));
            students.add(new Student("Dave", 20));
            System.out.println("Before sorting: " + students);
            Collections.sort(students, comparator);
            System.out.println("After sorting: " + students);    
        }
    }