28

If I implement java.lang.Comparable for a class, do I still have to override the equals() method? Or will the Comparable work for equals as well?

If the answer is no, then what if some discrepancy arises? Let's say the way I term two objects as equal within the equals() method is different from the way I term two objects of the same class as equal within the compareTo() of the Comparable.

Moreover, if I implement Comparable, do I also have to override equals()?

stkent
  • 19,772
  • 14
  • 85
  • 111
aps
  • 2,452
  • 10
  • 35
  • 47

4 Answers4

31

While it is recommended (and pretty sensible) that having a.compareTo(b) == 0 imply that a.equals(b) (and visa versa), it is not required. Comparable is intended to be used when performing an ordering on a series of objects, whereas equals() just tests for straight equality.

This link has some good information on implementing compareTo properly.

dlev
  • 48,024
  • 5
  • 125
  • 132
  • +1 here's a link to the relevant Effective Java's chapters (see item 11) http://java.sun.com/developer/Books/effectivejava/Chapter3.pdf – MByD Aug 07 '11 at 05:22
  • @MByD Thanks for the link. It (unsurprisingly) says it better than I do! – dlev Aug 07 '11 at 05:24
  • @MbyD thanks for the link. Is it ok to call a.compareTo(b) or compare() directly? – aps Aug 07 '11 at 05:28
  • @aps - why wouldn't it be? please note - if you override the equals() method, you should also **must** override the hashCode() method. – MByD Aug 07 '11 at 05:31
  • @aps If at some point in your code you would like to know how `a` compares to `b`, then you can go right ahead. – dlev Aug 07 '11 at 05:31
  • Ok. So, I have a class with a natural ordering which I have specified using the Comparable interface. Now I want to see how two objects of that class compares with each other based on some other criteria. So should I just create an object of a class which implements Comparator and create a new object of that class, and then call compare(o1,o2)? – aps Aug 07 '11 at 05:39
  • @aps: Yep, implementing `Comparator` is what you do when the comparison you want to make doesn't follow the natural order of the class. – Mark Peters Aug 07 '11 at 05:42
  • @aps When you say "based on some other criteria", do you mean different than the natural order you've imposed? If so, then creating a `Comparator` is the way to go. – dlev Aug 07 '11 at 05:42
  • I don't want to sort the whole collection, just see how two objects compare. – aps Aug 07 '11 at 05:54
  • @aps That's fine. `Comparator` just defines a two-argument `compare()` method; you can call it on your objects and inspect the result. – dlev Aug 07 '11 at 05:55
8

From Javadoc of java.lang.Comparable:

It is strongly recommended (though not required) that natural orderings be consistent with equals.

Andrey Adamovich
  • 20,285
  • 14
  • 94
  • 132
5

While it is recommended, it is not required that .equals() and .compareTo() have the same behaviour.

Just look at the BigDecimal Docs for equals() method:

Unlike compareTo, this method considers two BigDecimal objects equal only if they are equal in value and scale (thus 2.0 is not equal to 2.00 when compared by this method).

BigDecimal is a core class of java that has different behaviour for equals() and compareTo() and serves as a good example of the difference between 2 objects that are comparable vs truly equal.

gnomed
  • 5,483
  • 2
  • 26
  • 28
1

Let's say the way I term two objects as equal within the equals() method is different from the way I term two objects of the same class as equal within the toCompare() of the Comparable?

If you do this, and you put those objects into a sorted set, the set will misbehave. From the docs on SortedSet:

Note that the ordering maintained by a sorted set (whether or not an explicit comparator is provided) must be consistent with equals if the sorted set is to correctly implement the Set interface.

For example, a TreeSet may (erroneously) contain two objects where

a.compareTo(b) != 0

even though

a.equals(b) == true
SharkAlley
  • 11,399
  • 5
  • 51
  • 42
  • 1
    All `TreeSet` operations are performed using `compareTo` - so objects that the comparison returns `!= 0` are considered distinct, and objects that the comparison returns `== 0` are identical (and thus only the first one added to the set is actually retained). As the Javadoc says: `The behavior of a sorted set is well-defined even if its ordering is inconsistent with equals; it just fails to obey the general contract of the Set interface.` – Greg Kopff Jan 17 '14 at 06:23
  • 1
    People regularly get bitten by this behaviour of `TreeSet`: e.g. https://stackoverflow.com/q/22123336/587365 https://stackoverflow.com/q/11082197/587365 https://stackoverflow.com/q/23489718/587365 – Andrew Spencer Mar 29 '18 at 13:34