0

Java Strings: compareTo() vs. equals()

The author mentions

"compareTo() is meant to provide an ordering and not compare for equality) and even somewhat dangerous (because compareTo() == 0 does not necessarily imply equality in all cases..."

What are those cases?

In which cases compareTo()=0 does not imply equality between two strings?

Community
  • 1
  • 1
Arthas
  • 145
  • 1
  • 12
  • 2
    OpenJDK 6-b14 Javadoc sais: "The result is zero if the strings are equal; compareTo returns 0 exactly when the equals(java.lang.Object) method would return true." – Fildor Aug 22 '16 at 10:31
  • 2
    Also Java 8 Javadoc: https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#compareTo-java.lang.String- "**The result is zero if the strings are equal;** compareTo returns 0 exactly when the equals(Object) method would return true." So either I read the documentation wrong or the author should be held accountable for providing examples. – Fildor Aug 22 '16 at 10:32
  • looking at the documentation it looks like there is no possibility of the cases mentioned by the author yet no one mentioned it in the answers of that post so there may be a possibility of such a case? – Arthas Aug 22 '16 at 10:38
  • 1
    I was looking from `String`'s perspective, only. But Ashwinee is right: The Comparable interface contract states: "It is strongly recommended, **but not strictly required** that (x.compareTo(y)==0) == (x.equals(y)).". But I do not think this applies for `String`. (I am assuming we are talking about non-null values). – Fildor Aug 22 '16 at 10:40
  • If `equals()` and `compareTo()` aren't consistent, you have bigger problems to worry about. For example `TreeSet` will act weird. – biziclop Aug 22 '16 at 10:42
  • 1
    There is no danger, and there is nothing in the correct answers to your link that says otherwise. There is an efficiency concern, and a difference of behaviour when the second operand is null. – user207421 Aug 22 '16 at 10:43
  • 4
    Read the post http://stackoverflow.com/questions/1551235/java-strings-compareto-vs-equals exactly: the author writes: "because compareTo() == 0 does not necessarily imply equality in all cases, **even though I know it does for String's**". So the author is well aware of the fact that for Strings there is no logical difference (but maybe performance wise for Strings of different lengths). – Thomas Kläger Aug 22 '16 at 10:44
  • It was really stupid of me to miss out what the author wrote about strings sorry if I have wasted time of you guys, however the answer provided ashwinee was an interesting read and somewhat answer to my possible question beyond the scope of strings. Apologies guys – Arthas Aug 22 '16 at 13:31

2 Answers2

0

Comparable interface can be implemented by any class so there is no guarantee that equals() == true and compareTo() == 0 will always imply each other.

I guess that is what the other thread talked about. Note that for String both are same, equals() == true implies compareTo() == 0.

However you can see here https://softwareengineering.stackexchange.com/questions/283030/legitimate-cases-of-having-equals-behaving-inconsistently-with-compareto that there are legtimate cases where equals and compareTo have different semantics.

Community
  • 1
  • 1
Ashwinee K Jha
  • 9,187
  • 2
  • 25
  • 19
0
 public int compareTo(String anotherString) {
        int len1 = value.length;
        int len2 = anotherString.value.length;
        int lim = Math.min(len1, len2);
        char v1[] = value;
        char v2[] = anotherString.value;

        int k = 0;
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;
            }
            k++;
        }
        return len1 - len2;
    }

and equals is

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

So as mentioned in original post it different behavior for null. If you will compare you String with null it will throw NullPointerException, and will be ok with equals

Anton Kolyaev
  • 306
  • 2
  • 10