Item 12: Consider implementing comparable

Usually while thinking of real time examples for a code solution, one often ends up comparing two objects. e.g. listing the companies in IT in the reverse order of their turnovers. This needs some comparison between 2 instances of object say TurnOver. Enough for the intro, the title tells you where exactly I am heading.

Advantages of implementing comparable

  1. Implement for natural comparing
  2. TreeSet uses compareTo for comparing and sorting a set
  3. HashSet uses equals to avoid redundant keys
  4. Arrays.sort(a); can be used where ‘a’ is an array of comaprable object

General Contract of compareTo method

To cut the story short:

  1. Must return 1, -1 or 0 only
  2. If something acts as a constraint in comparing the two objects, throw a ClassCastException
  3. Throws a NullPointerException
  4. The implementor must ensure sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y. (This implies that x.compareTo(y) must throw an exception if and only if y.compareTo(x) throws an exception)
  5. The implementor must also ensure that the relation is transitive: (x.compareTo(y) > 0 && y.compareTo(z) > 0) implies x.compareTo(z) > 0
  6. Finally, the implementor must ensure that x.compareTo(y) == 0 implies that sgn(x.compareTo(z)) == sgn(y.compareTo(z)), for all z
  7. It is strongly recommended, but not strictly required, that (x.compareTo(y) == 0) == (x.equals(y))

Generally speaking, any class that implements the Comparable interface and violates this condition should clearly indicate this fact. The recommended language is “Note: This class has a natural ordering that is inconsistent with equals.”

Example where equals and compareTo behave differently

Consider 2 BigDecimal objects instantiated with String values “1.00” and “1.0”.

Behavior of equals method of BigDecimal -What would the following code print?

BigDecimal bd1 = new BigDecimal("1.00");
BigDecimal bd2 = new BigDecimal("1.0");
System.out.println(bd1.equals(bd2));

This code prints a big fat false. While..

Behavior of compareTo method of BigDecimal -What does this piece of code print?

BigDecimal bd1 = new BigDecimal("1.00");
BigDecimal bd2 = new BigDecimal("1.0");
System.out.println(bd1.compareTo(bd2));

Wait for it ……..

Yes, it returns 0. I.e. there may be examples where the behavior of equals and compareTo may be different. But, such cases must be avoided.

Involve all the important fields in compareTo

Try and include all the relevant fields in compareTo. There may be times when one needs to sort a list on the basis of multiple fields. e.g. if the phone numbers are to be sorted according to the state code and area code, giving preference to the state code. Then a class PhoneNumber’s logic will use both state code and area code in compareTo logic.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: