Java Comparable vs Comparator

Java Comparable vs Comparator

Thanks TO:Java Development Journal

Comparable

public interface Comparable<T>

When a class implement?Comparable, the compareTo method of the class defines the “natural” ordering of that object. CompareTo method should follow general contracts, few of the examples are

  1. Should always be returned 0?for objects when?equal?()?comparisons return true.
  2. Comparable is useful when there’s a single natural default comparison.


Comparator

public Interface Comparator<T>

Comparator?provides a way to compare 2 objects and can compare objects in a way that might not align with the natural ordering.

One of the common examples is String, String is generally compared alphabetically,?” a”.compareTo(“b”)??would use alphabetical comparisons.If you want to compare based on the String length, writing custom Comparator is a preferred solution.

If you do not have control over the source code (?where you can not implement Comparable?), then use Comparator.Comparator is useful when you have multiple ways to compare an object (?e.g you can compare cars by brand and cc etc.).

Both seem to be different, but to summarise, there isn’t much difference.Both ends to similar means. Implement comparable for natural order, and write a comparator for other sorting or comparison needs.

Java Sorting Example(Comparable and Comparator)

In this article, we will cover?Java Sorting Example (Comparable and Comparator). Java Collection API provides a way to sort Array?and Lists?but it expects input from the developer. This article will try to give an example to use both?java.lang.Comparable?and?java.util.Comparator?to sort objects.

?

1. Sort an ArrayList

Collections API’s utility class Collections?provide a handy way to sort an ArrayList in a natural ordering provided all elements in the list must implement?the Comparable?interface.

public class SimpleSorting {

    public static void main(String[] args) {

        List<String> locationList = new ArrayList<String>();
        locationList.add("California");
        locationList.add("Texas");
        locationList.add("Seattle");
        locationList.add("New Delhi");

        Collections.sort(locationList);

        for (String location?: locationList) {
            System.out.println("Location is: " + location);
        }
    }
}        

Output

Location is: California
Location is: New Delhi
Location is: Seattle
Location is: Texas        

Above example worked perfectly with Collections.Sort() as List defined in example was Lits<String> and java.lang.String implements the Comparable interface. With List contains custom objects, Collections.sort() will fail if the custom object does not implement the Comparable interface.

?

2. Sort?Object?using?Comparable

public class Person implements Comparable<Person> {

    private String name;
    private int age;

    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int compareTo(Person person) {
        return this.age > person.age?? 1?: this.age < person.age?? -1?: 0;
    }
}        

To sort it, we will use Collections.sort() method

public class ComparableDemo {

    public static void main(String[] args) {

        List<Person> persons = new ArrayList<Person>();

        persons.add(new Person("Umesh Awasthi", 35));
        persons.add(new Person("Robert Hickle", 55));
        persons.add(new Person("John Smith", 40));
        persons.add(new Person("David", 23));

        Collections.sort(persons);

        for (Person person?: persons) {
            System.out.println("Person is: " + person.getName());
        }

    }
}        

Output is

Person is: David
Person is: Umesh Awasthi
Person is: John Smith
Person is: Robert Hickle        

Pay close attention to Person class declaration?public class Person implements Comparable<Person>?which shows that Person class is a comparable if you remove?Comparable<Person> from your Person class and try?Collection.sort(persons)?, compile will give the following error

Error:(21, 20) java: no suitable method found for sort(java.util.List<com.umeshawasthi.tutorials.corejava.sorting.Person>)
    method java.util.Collections.<T>sort(java.util.List<T>) is not applicable
      (inferred type does not conform to upper bound(s)
        inferred: com.umeshawasthi.tutorials.corejava.sorting.Person
        upper bound(s): java.lang.Comparable<? super com.umeshawasthi.tutorials.corejava.sorting.Person>)
    method java.util.Collections.<T>sort(java.util.List<T>,java.util.Comparator<? super T>) is not applicable
      (cannot infer type-variable(s) T
        (actual and formal argument lists differ in length))        

As a developer, it’s out responsibility to pass the comparable?object to?Collections.sort()?method.

It’s up to you how you want to use the compareTo method and what will be your comparison?logic, I have used a simple logic to compare the age of the person but you can use any custom logic to in?compareTo()?method.

?

3. Sort?Object?using?Comparator

java.lang.Comparable interface provides only one way to compare this object with another one, what are the options in case we need to compare 2 objects to sort them correctly. How about sorting Person with a name or age??What if we want to?override the natural ordering? We need to create a Comparator for these requirements.

First and super short template is to provide a custom comparator while calling?Collections.sort()?method

public class ComparatorDemo {

    public static void main(String[] args) {
        List<Person> persons = new ArrayList<Person>();

        persons.add(new Person("Umesh Awasthi", 35));
        persons.add(new Person("Robert Hickle", 55));
        persons.add(new Person("John Smith", 40));
        persons.add(new Person("David", 23));
        persons.add(new Person("David", 63));

        Collections.sort(persons, new Comparator<Person>() {
            public int compare(Person person, Person person1) {
                int name = person.getName().compareTo(person1.getName());
                if(name == 0){
                    return name;
                }
                return person.getAge() > person1.getAge()?? 1?: person.getAge() < person1.getAge()?? -1?: 0;
            }
        });


        for (Person person?: persons) {
            System.out.println("Person is: " + person.getName());
        }
    }
}        

Output

Person is: David
Person is: Umesh Awasthi
Person is: John Smith
Person is: Robert Hickle
Person is: David        

Check the output, the interesting part is David, which is first and last result of the output.Another efficient way is to?define the Comparators in the Contact itself to reuse them instead of recreating every time

public class ComparatorPerson {

    private String name;
    private int age;

    public ComparatorPerson(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public static Comparator<ComparatorPerson> COMPARE_BY_NAME = new Comparator<ComparatorPerson>() {
        public int compare(ComparatorPerson one, ComparatorPerson other) {
            return one.name.compareTo(other.name);
        }
    };

    public static Comparator<ComparatorPerson> COMPARE_BY_AGE = new Comparator<ComparatorPerson>() {
        public int compare(ComparatorPerson one, ComparatorPerson other) {
            return one.age > other.age?? 1?: one.age < other.age?? -1?: 0;
        }
    };
}        

Comparator with multi options

public class MultiComparatorDemo {
    public static void main(String[] args) {
        List<ComparatorPerson> persons = new ArrayList<ComparatorPerson>();

        persons.add(new ComparatorPerson("Umesh Awasthi", 35));
        persons.add(new ComparatorPerson("Robert Hickle", 55));
        persons.add(new ComparatorPerson("John Smith", 40));
        persons.add(new ComparatorPerson("David", 23));
        persons.add(new ComparatorPerson("David", 63));

        Collections.sort(persons,ComparatorPerson.COMPARE_BY_AGE?);

        for (ComparatorPerson person?: persons) {
            System.out.println("Person Name Sorted by Age is: " + person.getName());
        }

        System.out.println("######################################################");
        Collections.sort(persons,ComparatorPerson.COMPARE_BY_NAME?);

        for (ComparatorPerson person?: persons) {
            System.out.println("Person Name Sorted by Name  is: " + person.getName());
        }
    }
}        

Output

Person Name Sorted by Age is: David
Person Name Sorted by Age is: Umesh Awasthi
Person Name Sorted by Age is: John Smith
Person Name Sorted by Age is: Robert Hickle
Person Name Sorted by Age is: David
######################################################
Person Name Sorted by Name  is: David
Person Name Sorted by Name  is: David
Person Name Sorted by Name  is: John Smith
Person Name Sorted by Name  is: Robert Hickle
Person Name Sorted by Name  is: Umesh Awasthi        

?

4. Sort?Object?using?Java8

Java 8?added a new way of making Comparators that reduces the amount of code you have to write?Comparator.comparing. Java 8 streaming API provides neater approach. It’s always good to understand how?compareTo()?and?compare()?method work under the hood

public class Java8CompareExample {

    public static void main(String[] args) {

        List<Person> persons = new ArrayList<Person>();

        persons.add(new Person("Umesh Awasthi", 35));
        persons.add(new Person("Robert Hickle", 55));
        persons.add(new Person("John Smith", 40));
        persons.add(new Person("David", 23));
        persons.add(new Person("David", 63));

        persons.sort(Comparator.comparing(Person::getName).thenComparingInt(Person::getAge));

        for (Person person?: persons) {
            System.out.println("Person Name is: " + person.getName());
        }

        persons.sort(Comparator.comparingInt(Person::getAge).thenComparing(Person::getName));

        for (Person person?: persons) {
            System.out.println("Person Name is: " + person.getName());
        }
    }
}        

In this article, we cover?Java Sorting Example (Comparable and Comparator) provided by JDK, we will cover other API which provides the same functionalities with additional features. All the code of this article is available?Over on Github. This is a Maven-based project. As a bonus, have a look at?Apache Common ComparatorUtils?which provide some ready-to-use a feature for you.

  • Comparable is meant for objects with natural ordering which means the object itself must know how it is to be ordered. For example Roll Numbers of students. Whereas, Comparator interface sorting is done through a separate class.
  • Logically, Comparable interface compares “this” reference with the object specified and Comparator in Java compares two different class objects provided.
  • If any class implements Comparable interface in Java then collection of that object either List or Array can be sorted automatically by using Collections.sort() or Arrays.sort() method and objects will be sorted based on there natural order defined by CompareTo method.
  • A basic differentiating feature is that using comparable we can use only one comparison. Whereas, we can write more than one custom comparators as you want for a given type, all using different interpretations of what sorting means. Like in the comparable example we could just sort by only one attribute, i.e., year but in the comparator, we were able to use different attributes like rating, name, and year as well.

?

To summarize, if sorting of objects needs to be based on natural order then use Comparable whereas if you sorting needs to be done on attributes of different objects, then use Comparator in Java.


Reference

  1. Comparator
  2. Comparable
  3. Comparator.comparing
  4. geeksforgeeks


要查看或添加评论,请登录

社区洞察

其他会员也浏览了