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 by the natural ordering of its elements. The natural ordering of an object can be defined by implementing the Comparable interface in the corresponding class. 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 List's elements according to the given Comparator. Their natural ordering will be ignored for the sorting. This second method comes in hand when the List's elements already possess their natural ordering but we want to order them by a different criteria.

    Here's a simple example with a Person class displaying name, last name and age.

    class Person implements Comparable<Person> {
        private String name, lastName;
        private int age;
    
        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) {
            //Defining Person's natural ordering by creating a comparator and comparing by last name and then name the current object and the given paramter 
            return Comparator.comparing(Person::getLastName).thenComparing(Person::getName).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("Matt", "O'Brien", 30),
                    new Person("Conan", "O'Brien", 25),
                    new Person("Frank", "Johnson", 50)
            ));
    
            //Original unordered list
            System.out.println(list);
    
            //List ordered by Person's natural ordering (last name and then name)
            Collections.sort(list);
            System.out.println(list);
    
            //List ordered by custom criteria (age)
            Collections.sort(list, Comparator.comparing(Person::getAge));
            System.out.println(list);
        }
    }