4

Could anyone please explain me whether there's any difference in the codes below when comparing objects and more specifically their values.

Code 1

x.equals(y)

Code 2

x.compareTo(y) == 0

Are the codes above interchangeable. What's the difference if any?

Alexis C.
  • 91,686
  • 21
  • 171
  • 177
user3149650
  • 213
  • 2
  • 12
  • 5
    `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."` – nachokk Jan 17 '14 at 14:25
  • 2
    _"The natural ordering for a class C is said to be consistent with equals if and only if e1.compareTo(e2) == 0 has the same boolean value as e1.equals(e2) for every e1 and e2 of class C. Note that null is not an instance of any class, and **e.compareTo(null)** should throw a **NullPointerException** even though **e.equals(null)** returns **false**."_ – Alexis C. Jan 17 '14 at 14:25

3 Answers3

2

From Comparable

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."

As @ZouZou mention

The natural ordering for a class C is said to be consistent with equals if and only if e1.compareTo(e2) == 0 has the same boolean value as e1.equals(e2) for every e1 and e2 of class C. Note that null is not an instance of any class, and e.compareTo(null) should throw a NullPointerException even though e.equals(null) returns false.

That means they are not interchangable.

An example where this happen in java api is in BigDecimal

import java.math.BigDecimal;

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

       BigDecimal big = BigDecimal.ZERO;
       BigDecimal zero  = new BigDecimal("0.00");

       System.out.println("Compare "+ (big.compareTo(zero) == 0) ); //prints true
       System.out.println("Equals "+big.equals(zero)); // prints false      
 } 
}
nachokk
  • 14,363
  • 4
  • 24
  • 53
  • 1
    One notable example of a class where `equals()` is inconsistent with `compareTo()` is [`BigDecimal`](http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html) – axtavt Jan 17 '14 at 14:46
  • And a reminder that if you are overriding equals(Object) make sure you also override hashCode() to be consistent with equals. ["If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result."](http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Object.html#hashCode()) – Victor Jan 17 '14 at 15:29
  • @Victor good advice but it's not related to this question. – nachokk Jan 17 '14 at 15:32
1

compareTo doesn't always make sense, sometimes the objects cannot be logically ordered.
Also note that equals always exists, since it's defined in Object class.

It's a good practice to always haven equals method when you have compareTo, and they should be consistent.

Also you might want to have a look at this question.

Community
  • 1
  • 1
Maroun
  • 94,125
  • 30
  • 188
  • 241
0

It is not interchangeable for Strings.

x.equals((String)null)  returns false

Code 2

x.compareTo((String)null) == 0 // throws a NullPointerException

See here:Java Strings: compareTo() vs. equals()

Community
  • 1
  • 1
Sitansu
  • 3,225
  • 8
  • 34
  • 61