简体   繁体   中英

Difference between Comparable and Comparator?

My understand is Comparator can compare multiple objects from different classes while Comparable can only compare one onject with another instance in the same class.

Compareto (object1) Compare(object1, object2)

Is the above explanation is true??

Not really.
Comparable and Comparator are generic interfaces that allow to compare instances of the type defined in the generic (subclasses included).

The main difference between them is that Comparable is directly implemented in the class which you want to compare objects.

Consequently, if you have a single way to compare instances from a class, that is that you have a natural order for them, Comparable is the right approach.
On the other hand, if you have multiple ways to compare instances from a class, Comparable is not enough.
You should use Comparator s instead (if it doesn't exist a natural order) or use both (if it exists a natural order and some other kinds of order).


Example where Comparator can be useful in addition to Comparable :

The String class implements Comparable by comparing two strings lexicographically. Suppose you need to sort a List of String according to a different rule : their length.
You will need to define a Comparator<String> that implements this rule such as :

public class StringLengthComparator implements Comparator<String> {

    @Override
    public int compare(String o1, String o2) {
        return Integer.compare(o1.length(), o2.length());
    }

}

Now you could sort String s by using their natural order (using Comparable ) :

List<String> strings = new ArrayList<>();
...
strings.sort();

But you could also use a specific Comparator<String> :

strings.sort(new StringLengthComparator());

Or without creating any class with a lambda:

strings.sort((o1,o2)->Integer.compare(o1.length(), o2.length()));

Example where Comparator should be used instead of Comparable :

Suppose you have an Account class that represents a bank account.
Functionally you don't have a natural order to sort them but you have instead multiple orders according to the client needs. Making the class to implement Comparable would not make sense. But creating distinct Comparator<Account> would.


Case where only Comparator can be used :

If you want to define a order for instances of a class which you cannot change the source code (JDK class or third party class), Comparator is the way to follow.

This answer is based on the information extracted from the Complete Java SE 8 Developer Bootcamp course by Intertech Training. According to them

The Comparable interface says “This particular object is gonna be compared to another object” whereas the Comparator is kind of like this third-party “give me any two objects and I'll tell you how they're ordered”.

Both Comparable and Comparator are located in java.util.package .

Strings, charts, ints, and so on all have a “natural ordering” (following the unicode, so the highest precedence in ordering would be numbers, then capital letters and lower case letters). If we're going to sort custom classes, then we'll have to implement a Comparable interface to help the sorting methods understand what they should do (to get Collections or Arrays to sort your types, the types must implement the Comparable interface).

A class implementing the Comparable interface must implement the compareTo() method. This method takes a generic Object. For instance,

public class MyDate implements Comparable {
    private int day, month, year;
    public MyDate(int month, int day, int year) {
        this.day = day;
        this.year = year;
        this.month = month;
    }
    public int compareTo(Object o) {
        MyDate d = (MyDate) o;
        if (year != d.year) {
            return year - d.year;
        }
        if (month != d.month ) {
            return month - d.month;
        }
        if (day != d.day) {
            return day - d.day;
        }
        return 0;
    }
    ...
}

A class implementing the Comparator interface must implement the compare() method. This method takes two Objects as arguments and returns a positive number if the first argument is larger than the second, zero if they are equal, and a negative number otherwise.

public class MyDate implements Comparator {
    private int day, month, year;
    public MyDate(int month, int day, int year) {
        this.day = day;
        this.year = year;
        this.month = month;
    }
    public int compare(Object o1, Object o2) {
        MyDate d1 = (MyDate) o1;
        MyDate d2 = (MyDate) o2;
        if (d1.year != d2.year) {
            return d1.year - d2.year;
        }
        if (d1.month != d2.month ) {
            return d1.month - d2.month;
        }
        if (d1.day != d2.day) {
            return d1.day - d2.day;
        }
        return 0;
    }
    ...
}

A Comparator can be used to compare any two objects. When comparing like objects, it is best to use the Comparable interface when possible.

The Comparator is useful when comparing elements of a heterogeneous collection and third-party classes we don't have the source to.

I think that when we want compare a user defined class by multiple attribute naturally ,is better that we use from Comparator interface that permitted us create some classes that implemented comparator interface and compare each one of attributes.in this case we have a below code :

public class Student{
private String name;
private String ranking;
private int age;
private String country;

// getter and setter
}

public class NameComparator implements Comparator{
//compare by name attribute
}
public class AgeComparator implements Comparator{
//compare by Age attribute
}
public class CountryComparator implements Comparator{
//compare by Country attribute
}
public class RankingComparator implements Comparator{
//compare by Ranking attribute
}

But when we want compare a user defined class by using just one attribute There is no need to comparator , instead of it we can use comparable interface as below code:

public class Student{
private String name;
private String ranking;
private int age;
private String country;

// getter and setter

public int CompareTo(Object obj1){
//implement comparation by name or age or etc
}
}

And one of the place that is good , if we used from Comparator interface is for built in classes that have implemented CompareTo method such as number and etc.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM