Why should a Java class implement comparable?

Why is Java Comparable used? Why would someone implement Comparable in a class? What is a real life example where you need to implement comparable?


Solution 1:

Here is a real life sample. Note that String also implements Comparable.

class Author implements Comparable<Author>{
    String firstName;
    String lastName;

    @Override
    public int compareTo(Author other){
        // compareTo should return < 0 if this is supposed to be
        // less than other, > 0 if this is supposed to be greater than 
        // other and 0 if they are supposed to be equal
        int last = this.lastName.compareTo(other.lastName);
        return last == 0 ? this.firstName.compareTo(other.firstName) : last;
    }
}

later..

/**
 * List the authors. Sort them by name so it will look good.
 */
public List<Author> listAuthors(){
    List<Author> authors = readAuthorsFromFileOrSomething();
    Collections.sort(authors);
    return authors;
}

/**
 * List unique authors. Sort them by name so it will look good.
 */
public SortedSet<Author> listUniqueAuthors(){
    List<Author> authors = readAuthorsFromFileOrSomething();
    return new TreeSet<Author>(authors);
}

Solution 2:

Comparable defines a natural ordering. What this means is that you're defining it when one object should be considered "less than" or "greater than".

Suppose you have a bunch of integers and you want to sort them. That's pretty easy, just put them in a sorted collection, right?

TreeSet<Integer> m = new TreeSet<Integer>(); 
m.add(1);
m.add(3);
m.add(2);
for (Integer i : m)
... // values will be sorted

But now suppose I have some custom object, where sorting makes sense to me, but is undefined. Let's say, I have data representing districts by zipcode with population density, and I want to sort them by density:

public class District {
  String zipcode; 
  Double populationDensity;
}

Now the easiest way to sort them is to define them with a natural ordering by implementing Comparable, which means there's a standard way these objects are defined to be ordered.:

public class District implements Comparable<District>{
  String zipcode; 
  Double populationDensity;
  public int compareTo(District other)
  {
    return populationDensity.compareTo(other.populationDensity);
  }
}

Note that you can do the equivalent thing by defining a comparator. The difference is that the comparator defines the ordering logic outside the object. Maybe in a separate process I need to order the same objects by zipcode - in that case the ordering isn't necessarily a property of the object, or differs from the objects natural ordering. You could use an external comparator to define a custom ordering on integers, for example by sorting them by their alphabetical value.

Basically the ordering logic has to exist somewhere. That can be -

  • in the object itself, if it's naturally comparable (extends Comparable -e.g. integers)

  • supplied in an external comparator, as in the example above.