'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 1:[1]

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);
    }
}

Solution 2:[2]

If Sellable implements the interface Comparable you can use Collections.sort(list). Otherwise you should create own Comparator and use Collections.sort(list, comparator). Because there must be a rule by which to compare elements of the Sellable type.

Solution 3:[3]

You don't need to provide a comparator when objects contained in the list implement Comparable interface.

Comparator & Comparator

That's how the purpose of this interface defined by the documention:

This interface imposes a total ordering on the objects of each class that implements it. This ordering is referred to as the class's natural ordering, and the class's compareTo method is referred to as its natural comparison method.

On the other hand, comparator - is an object that is used to provide an ordering for collections of objects that don't have a natural ordering, i.e. there's no obvious specific way in which these object can be ordered, and their class doesn't implement Comparable.

Comparators are handy when objects are required to be ordered in differently depending on the situation. For instance, you have a class Student, and students can be sorted by their names, ids, grades, etc. And you can create a comparator for each of these cases either by creating a class implementing the interface Comparator and overrides method compare() (like in the code you've listed) or by making use of the static methods like Comparator.comparing() introduced with Java 8.

With that said, interfaces Comparator and Comparable serve the same purpose (to facilitate comparison of object), but have different use cases.

Caution: don't mix things together by creating a comparator inside the compareTo() method, as it's shown in another answer. It's a terrible idea. Why? Because such an implementation will create a new comparator for every invocation of this method. To sort a list of 10.000.000 elements, 10.000.000 * log(10.000.000) comparisons will be required, with each comparison compareTo() will be called and a new instance of comparator will be created. It'll have a negative impact on the application performance because creation of objects is costful, it requires memory allocation and then gives loads of work to the garbage collector.

Fluent sorting

In order to sort a list, you can use static methods sort() from the Collections utility class, that are part of the JDK since the very early version. And you could find lots code-snippets on the Internet, where Collection.sort() is being used.

With Java 8 method List#sort() was introduced in the List interface and you no longer need to resort to static methods from the Collections class. Instead you can directly invoke method sort() on the list, note that it always expects a comparator as an argument. If elements of the list implement Comparable you should pass null instead:

If the specified comparator is null then all elements in this list must implement the Comparable interface and the elements' natural ordering should be used.

myList.sort(null); // only if element of the implement Comparable

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 yuri777
Solution 3 Alexander Ivanchenko