Search code examples
javalistsortingcomparatorcomparable

Difference between Collections.sort(list) and Collections.sort(list,comparator)


What's the difference between:

    public FlyingRabbit(){
        list = new ArrayList<Sellable>();
    }
    public void sort(Comparator<Sellable> comp) {
        Collections.sort(list, comp);
    }

and:

public class CompareCategory implements Comparator<Sellable> {
    @Override
    public int compare(Sellable s1, Sellable s2) {
            return (s1.getCategory()).compareTo(s2.getCategory());
    }
}

I'm confused about why do I need to use the Comparator comp instead of using compare inside CompareCategory.


Solution

  • Collections.sort(List<T>) sorts the given List according to the natural ordering of its elements. A class can define its natural ordering by implementing the Comparable interface. This interface provides a single method, compareTo(), which returns:

    a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.

    On the other hand, Collections.sort(List<T>, Comparator<T>) orders the elements of the List according to the given Comparator. The element's natural ordering is ignored. This second method comes in handy when the List's elements already exhibit a natural ordering, but we need to sort them by a different ordering.

    Here's a brief example with a list of Person. The list is first sorted by Person's natural ordering (lastName and name), and then by a given Comparator that compares only by age.

    class Person implements Comparable<Person> {
    
        private String name;
        private String lastName;
        private int age;
    
        // Defining Person's natural ordering by creating a comparator that compares by last name and name
        private static final Comparator<Person> naturalOrdering = Comparator.comparing(Person::getLastName).thenComparing(Person::getName);
    
        public Person(String name, String lastName, int age) {
            this.name = name;
            this.lastName = lastName;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public String getLastName() {
            return lastName;
        }
    
        public int getAge() {
            return age;
        }
    
        @Override
        public int compareTo(Person o) {
            return naturalOrdering.compare(this, o);
        }
    
        @Override
        public String toString() {
            return String.format("%s %s %d", name, lastName, age);
        }
    
        public static void main(String[] args) {
            List<Person> list = new ArrayList<>(List.of(
                    new Person("Luke", "O'Brien", 30),
                    new Person("Conan", "O'Brien", 25),
                    new Person("John", "Doe", 50)
            ));
    
            // Original unordered list
            System.out.println(list);
    
            // List ordered by Person's natural ordering (last name and name)
            Collections.sort(list);
            System.out.println(list);
    
            // List ordered by custom comparator (age)
            Collections.sort(list, Comparator.comparing(Person::getAge));
            System.out.println(list);
        }
    }