How to use Comparator and Comparable interface in Java?

java_compare.png

Sort an Array

To sort an Array, use the Arrays.sort().

String[] planets = new String[] {"Mercury","Venus", "Earth", "Mars"};
Arrays.sort(planets);
System.out.println(Arrays.toString(planets));

Sort an ArrayList

To sort an ArrayList, use the Collections.sort().

List<String> planets = new ArrayList<String>();
planets.add("Mercury");
planets.add("Venus");
planets.add("Earth");
planets.add("Mars");

Collections.sort(planets);
System.out.println(planets);

Comparable interface

Java Comparable interface is used to order the objects of user-defined class by one parametere. This interface is found in java.lang package and contains only one method named compareTo(Object). It provides a way to sort the elements on single data member only. For example it may be ID, title, rating or anything else.

Comparable interface is used to implement natural ordering (if numbers then 1,2,3 or in alphabetical order 'a','b','c' ) of object. In Java API String, Date and wrapper classes implements Comparable interface. Its always good practice to override compareTo() for value objects. This method returns an int which tells if the values compare less than, equal, or greater than.

All Java classes (String, Double, BigInteger, etc.) that have a natural ordering implement this interface.

import java.util.*;
import java.io.*;
public class Example {
    static class Movie implements Comparable<Movie>{
        long movieID;
        String title;
        double rating;

        Movie(long movieID, String title, double rating) {
            this.movieID = movieID;
            this.title = title;
            this.rating = rating;
        }

        public int compareTo(Movie movie){
            if (rating == movie.rating)
                return 0;
            else if (rating > movie.rating)
                return 1;
            else
                return -1;
        }
    }

    public static void main(String[] args) {
        ArrayList<Movie> movies = new ArrayList<>();
        movies.add(new Movie(1, "Movie 1", 6.7));
        movies.add(new Movie(2, "Movie 2", 4.3));
        movies.add(new Movie(3, "Movie 2", 8.1));

        Collections.sort(movies);
        for(Movie movie : movies) {
            System.out.println(movie.movieID + " " + movie.title + " " + movie.rating);
        }
    }
}

Outcome of Comparable interface

  1. Comparable interface in Java is used to implement natural ordering of object.
  2. If any class implement 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.
  3. Objects which implement Comparable interface in Java can be used as keys in a SortedMap like treemap or elements in a SortedSet for example TreeSet, without specifying any Comparator.

Comparator interface

Java Comparator interface is used to order the objects of user-defined class by different parameteres, when an extra logic is required to sort the objects. This interface is found in java.util package and contains two methods compare(Object obj1, Object obj2) and equals(Object element).

The typical use is to define one or more small utility classes that implement this interface, to pass to methods such as sort() or for use by sorting data structures such as TreeMap and TreeSet. You might want to create a Comparator object for the following.

  • Multiple comparisons. To provide several different ways to sort something. For example, you might want to sort a Movie class by ID, title, rating, etc. You would define a Comparator for each of these to pass to the sort() method.
  • System class. To provide comparison methods for classes that you have no control over. For example, you could define a Comparator for String that compared them by length.
  • Strategy pattern. To implement a strategy pattern, which is a situation where you want to represent an algorithm as an object that you can pass as a parameter, save in a data structure, etc.

As mentioned, Comparator interface has method compare(Object obj1, Object obj2) with obj1 and obj2 parameters that are the objects to be compared. This method returns zero if the objects are equal. It returns a positive value if obj1 is greater than obj2. Otherwise, a negative value is returned.

NOTE! When you want to compare objects, you need to know whether you should use == to see if they are the same object, or equals() to see if they may be a different object, but have the same value. This kind of error can be very hard to find.

Following class contains three fields ID, title, rating and a parameterized constructor.

// file Movie.java
class Movie {
    long movieID;
    String title;
    double rating;

    Movie(long movieID, String title, double rating) {
        this.movieID = movieID;
        this.title = title;
        this.rating = rating;
    }
}

Next class defines comparison logic based on the rating field. If rating of first object is greater than the second, we are returning positive value, it can be any one such as 1, 2 , 10 etc. If rating of first object is less than the second object, we are returning negative value, it can be any negative value and if rating of both objects are equal, we are returning 0.

// file RatingComparator.java
class RatingComparator implements Comparator<Movie>{
    public int compare(Movie m1, Movie m2){
        if (m1.rating == m2.rating)
            return 0;
        else if(m1.rating > m2.rating)
            return 1;
        else
            return -1;
    }
}

Next class provides comparison logic based on the title field. In such case, we are using the compareTo() method of String class, which internally provides the comparison logic.

// file TitleComparator.java
class TitleComparator implements Comparator<Movie>{
    public int compare(Movie m1, Movie m2){
        return m1.name.compareTo(m2.name);
    }
}

After all, we are printing the objects values by sorting on the basis of title and rating.

class Example2 {
    public static void main(String args[]){

    ArrayList<Movie> movies = new ArrayList<>();
    movies.add(new Movie(1, "Movie 1", 6.7));
    movies.add(new Movie(2, "Movie 2", 4.3));
    movies.add(new Movie(3, "Movie 2", 8.1));

    System.out.println("Sorting by title ...");

    Collections.sort(movies, new TitleComparator());
    for(Movie movie : movies) {
        System.out.println(movie.movieID + " " + movie.title + " " + movie.rating);
    }

    System.out.println("Sorting by rating ...");

    Collections.sort(movies, new RatingComparator());
    for(Movie movie : movies) {
        System.out.println(movie.movieID + " " + movie.title + " " + movie.rating);
    }
}

Latest Lambda changes has made using Comparator a lot easier than ever before. Let's see by an example:

// sort all movies by title
movies.sort(Comparator.comparing(m -> m.title));

// sort all movies by first name in reverse order
Comparator<Movie> comparator = Comparator.comparing(m -> m.title);
movies.sort(comparator.reversed());

// sorting on multiple fields; group by.
Comparator<Movie> groupByComparator = Comparator.comparing(m -> m.title)
                                                   .thenComparing(m -> m.rating);
movies.sort(groupByComparator);

Difference between Comparable and Comparator

Comparable and Comparator both are interfaces and can be used to sort collection elements. But there are many differences between Comparable and Comparator interfaces that are given below.

Comparable Comparator
Comparable provides single sorting sequence. In other words, we can sort the collection on the basis of single element such as id or title or rating etc. Comparator provides multiple sorting sequence. In other words, we can sort the collection on the basis of multiple elements such as id, title and rating etc.
Comparable affects the original class i.e. actual class is modified. Comparator doesn't affect the original class i.e. actual class is not modified.
Comparable provides compareTo() method to sort elements. Comparator provides compare() method to sort elements.
Comparable is found in java.lang package. Comparator is found in java.util package.
We can sort the list elements of Comparable type by Collections.sort(List) method. We can sort the list elements of Comparator type by Collections.sort(List,Comparator) method.
comments powered by Disqus