A difference is that "foo".equals((String)null) returns false while "foo".compareTo((String)null) == 0 throws a NullPointerException. So they are not always interchangeable even for Strings.

Answer from waxwing on Stack Overflow
🌐
GeeksforGeeks
geeksforgeeks.org › java › java-equals-compareto-equalsignorecase-and-compare
Java | ==, equals(), compareTo(), equalsIgnoreCase() and compare() - GeeksforGeeks
November 21, 2018 - The compareTo() method compares strings lexicographically based on their Unicode values. It returns: 0 if both strings are equal · A negative value if the first string is smaller · A positive value if the first string is greater · JAVA ·
🌐
Coderanch
coderanch.com › t › 507821 › java › equals-compareTo-method-difference
equals and compareTo method difference? (Java in General forum at Coderanch)
That is, if a.compareTo(b) == 0, then a.equals(b) (and vice-versa). Recommended, not compulsory. Example: A lot of people rant about the BigDecimal#compareTo(java.math.BigDecimal) not being "consistent with equals", but I believe that is the correct way to implement it.
🌐
DZone
dzone.com › coding › languages › the hidden contract between equals and comparable
The Hidden Contract Between equals and Comparable
September 16, 2016 - The root of the problem is, when ... are equal, then we say both Glasses are meaningfully equivalent. But with the CompareTo method we only consider size....
🌐
YouTube
youtube.com › pace edu.
Equals vs compareTo Method in Java - YouTube
equals vs compareto in javacompareTo() vs. equals() javaequals(), compareTo(), and compare() JavaDifferentiate between compareTo and equalsJava String compar...
Published   March 5, 2022
Views   209
Top answer
1 of 4
15

The reason you have two different methods is that they do two different things.

The .equals method returns a boolean value indicating whether the object on which you call the method is equal to the object passed in as a parameter (for some definition of "is equal to" that is consistent with the nature of the object being compared).

The .compareTo method returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object. That makes it a useful method for sorting; it allows you to compare one instance with another for purposes of ordering.

When the Java documentation says that these two methods must behave consistently, what they mean is that the .equals method must return true in exactly the same situations where the .compareTo method returns zero, and must return false in exactly the same situations where the .compareTo method returns a nonzero number.

Is there any good reason to violate these rules? Generally no, for the same reasons that

#define TRUE FALSE

is a really bad idea. The only legitimate reason for inconsistent behavior is hinted at in the Java documentation itself: "[if the] class has a natural ordering that is inconsistent with equals."

To drive home the point, you can actually define .equals() in terms of compareTo(), thus guaranteeing consistent behavior. Consider this .equals() method from a Rational class which, after a few sanity checks, simply defines .equals as compareTo() == 0:

public boolean equals(Object y) {
    if (y == null) return false;
    if (y.getClass() != this.getClass()) return false;
    Rational b = (Rational) y;
    return compareTo(b) == 0;
}
2 of 4
8

This confusion would occur in situations where there are conflicting understandings of equals.

compareTo is 'easy' in that it asks a simple question 'which one is bigger?' If you were given a bunch of Things, how do you sort them?

equals on the other hand wants to ask 'are these the same thing?'

BigDecimal in Java is one such place where there are conflicting understandings of what it means to have two things being equal.

BigDecimal foo = new BigDecimal("1.00");
BigDecimal bar = new BigDecimal("1.000");

These two entires will have the same meaning for sorting. They, however, are not the same when it comes to equality. They have a different underlying state (the precision of the number) and that means they are not equal but foo.compareTo(bar) will return 0.

Consider this, if you had a Map qux = HashMap<BigDecimal, Object>() for some reason, do you want qux.put(foo,foo) to take the same spot as qux.put(bar,bar) and thus evict the earlier insertion?

So, while they are math equals (which is how compareTo sorts them), they are not inner state equals, and thus the necessity of the inconsistency here.

Yes, this inconsistency comes at the price of a higher cognitive load for dealing with BigDecimal. It means maps may not behave like you want them to... and the question is "which map do you want to behave 'right'?"

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.TreeMap;

class Main {
    public static void main (String[] args) {
        BigDecimal foo = new BigDecimal("1.00");
        BigDecimal bar = new BigDecimal("1.000");

        HashMap<BigDecimal, String> hash = new HashMap();
        TreeMap<BigDecimal, String> tree = new TreeMap();

        hash.put(foo, "foo");
        hash.put(bar, "bar");

        tree.put(foo, "foo");
        tree.put(bar, "bar");

        System.out.println("hash foo: " + hash.get(foo));
        System.out.println("hash bar: " + hash.get(bar));

        System.out.println("tree foo: " + tree.get(foo));
        System.out.println("tree bar: " + tree.get(bar));
    }
}

ideone

Output:

hash foo: foo
hash bar: bar
tree foo: bar
tree bar: bar

Because compareTo returned 0, in the TreeMap, bar evicted foo when bar was inserted. However, because these are different objects with different internal state and thus different hash codes, they were both able to exist within a HashMap.

From the docs:

Note: care should be exercised if BigDecimal objects are used as keys in a SortedMap or elements in a SortedSet since BigDecimal's natural ordering is inconsistent with equals. See Comparable, SortedMap or SortedSet for more information.

And so, thats the problem, the inconsistency and the "there's no good answer to this" dilemma.


One could also imagine this with a Rational class where one wants to keep 2/4 having the internal state of 2/4 so that:

Rational twoFourths = new Rational(2,4);
Rational oneHalf = new Rational(1,2);

System.out.println(twoFourths); // prints 2/4
System.out.println(oneHalf);    // prints 1/2
System.out.println(twoFourths.compareTo(oneHalf)); // prints 0
System.out.println(twoFourths.equals(oneHalf));    // ???

And you are once again up against that same question. Are these equal with the mathematical sense of equality (which means the hashCode needs to also return the same value?) or are they not equal using the object oriented state of the object sense of equality despite being the 'same'.

🌐
Baeldung
baeldung.com › home › java › core java › bigdecimal equals() vs. compareto()
BigDecimal equals() vs. compareTo() | Baeldung
May 2, 2024 - For BigDecimal.equals() to return ... also points to the same behavior: Unlike compareTo, this method considers two BigDecimal objects equal only if they are equal in value and scale....
Find elsewhere
🌐
Puc-rio
web.tecgraf.puc-rio.br › ~ismael › Cursos › apostilas › Java-Notes › data › expressions › 22compareobjects.html
Java: ==, .equals(), and compareTo()
The equals method and == and != operators test for equality/inequality, but do not provide a way to test for the relative values. Some classes (eg, String and other classes with a natural ordering) implement the Comparable<T> interface, which defines a compareTo method.
🌐
TutorialsPoint
tutorialspoint.com › what-is-the-difference-between-equals-and-compareto-in-java
What is the difference between equals and compareTo in Java?
The result is zero if the strings are equal, compareTo returns 0 exactly when the equals(Object) method would return true.
🌐
Rutgers CS
cs.rutgers.edu › courses › 111 › classes › fall_2011_venugopal › texts › notes-java › data › expressions › 22compareobjects.html
Java: ==, .equals(), compareTo(), and compare()
The equals method and == and != operators test for equality/inequality, but do not provide a way to test for relative values. Some classes (eg, String and other classes with a natural ordering) implement the Comparable<T> interface, which defines a compareTo method.
🌐
Sololearn
sololearn.com › en › Discuss › 890780 › differentiate-between-compareto-and-equals
Differentiate between compareTo() and equals(). | Sololearn: Learn to code for FREE!
java · 29th Nov 2017, 3:01 PM · Divyansh Saxena · 2 Answers · Answer · + 5 · compareTo() returns -1, 0, & 1 for <, =, & >. It lets you perform <= and >= by using the normal operators with 0. equals() returns true when both have same value ...
🌐
Quora
quora.com › When-should-and-equals-and-compareTo-be-used-in-Java
When should '==' and 'equals' and 'compareTo' be used in Java? - Quora
Answer: Here is the Java implementation of the above problem, which will be used for the purposes of this discussion: [code]public class Comparison { public static void main(String[] args) { String one = "abc", two = "abc"; String three = new String("abc"); String four = new String("abc")...
Top answer
1 of 4
58

Not all objects can be compared, but all objects can be checked for equality. If nothing else, one can see if two objects exist at the same location in memory (reference equality).

What does it mean to compareTo() on two Thread objects? How is one thread "greater than" another? How do you compare two ArrayList<T>s?

The Object contract applies to all Java classes. If even one class cannot be compared to other instances of its own class, then Object cannot require it to be part of the interface.

Joshua Bloch uses the key words "natural ordering" when explaining why a class might want to implement Comparable. Not every class has a natural ordering as I mentioned in my examples above, so not every class should implement Comparable nor should Object have the compareTo method.

...the compareTo method is not declared in Object. ... It is similar in character to Object's equals method, except that it permits order comparisons in addition to simple equality comparisons, and it is generic. By implementing Comparable, a class indicates that its instances have a natural ordering.

Effective Java, Second Edition: Joshua Bloch. Item 12, Page 62. Ellipses remove references to other chapters and code examples.

For cases where you do want to impose an ordering on a non-Comparable class that does not have a natural ordering, you can always supply a Comparator instance to help sort it.

2 of 4
8

The JLS §4.3.2 defines the class object in the following way:

4.3.2. The Class Object

The class Object is a superclass (§8.1.4) of all other classes.

All class and array types inherit (§8.4.8) the methods of class Object, which are summarized as follows:

  • The method clone is used to make a duplicate of an object.

  • The method equals defines a notion of object equality, which is based on value, not reference, comparison.

  • The method finalize is run just before an object is destroyed (§12.6).

  • The method getClass returns the Class object that represents the class of the object.

  • A Class object exists for each reference type. It can be used, for example, to discover the fully qualified name of a class, its members, its immediate superclass, and any interfaces that it implements.

    The type of a method invocation expression of getClass is Class<? extends |T|> where T is the class or interface searched (§15.12.1) for getClass.

    A class method that is declared synchronized (§8.4.3.6) synchronizes on the monitor associated with the Class object of the class.

  • The method hashCode is very useful, together with the method equals, in hashtables such as java.util.Hashmap.

  • The methods wait, notify, and notifyAll are used in concurrent programming using threads (§17.2).

  • The method toString returns a String representation of the object.

So, that's why equals is in Object but compareTo is in a separate interface. I would speculate that they wanted to keep Object as minimal as possible. They probably figured that nearly all Objects would need equals and hashCode (which is really just a form of equality testing) but not all objects would need to have a concept of ordering, which is what compareTo is used for.

🌐
W3Schools
w3schools.com › java › ref_string_compareto.asp
Java String compareTo() Method
The compareTo() method compares two strings lexicographically. The comparison is based on the Unicode value of each character in the strings. The method returns 0 if the string is equal to the other string.
🌐
Medium
medium.com › coding-corpus › java-important-methods-equals-hashcode-and-compareto-6adcdf2814c3
Java important methods— equals(), hashCode() and compareTo() | by Sourin Sutradhar | Programming Notes | Medium
June 8, 2017 - This stands in the same league of equals() and hashcode() and used to implement natural order of object. compareTo() method is defined in interface java.lang.Comparable and it is used to implement natural sorting on Java classes. Natural sorting means the the sort order which naturally applies on object e.g.