Sandeep is a ITA at Tata Consultancy Services. He also is the author of java blog. Sandeep has posted 24 posts at DZone. You can read more from them at their website. View Full User Profile

How String equals Method Works

11.23.2012
| 6023 views |
  • submit to reddit

The equals method is declared in Object class and hence is inherited by all classes in Java. The purpose of equals method is to provide logical equality. The default implementation of equals method is:

public boolean equals(Object obj) {
return (this == obj);
}
Thus the default behavior of equals method is same as == operator.

equals method in String class checks if the two strings have same characters or not. But this check is performed intelligently. The algorithm for checking the Strings for equality involves:

a) If the String objects are equals as per == operator, true is returned.
b) If the == returns false then each character of both the strings are compared and if a difference if found, immediately false is returned.
c) If after comparing all characters of both the strings, no difference is found in characters and length of strings, true is returned.

Please note that the equals method in String class in Java is case-sensitive. The complete code for equals method is reproduced here for reference:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}

Also the compareTo method in String class is consistent with equals method.

Published at DZone with permission of its author, Sandeep Bhandari. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Tomasz Nurkiewicz replied on Fri, 2012/11/23 - 2:55am

Point c) is not clear, it suggests that characters are compared first and if all of them are equal and length of strings is the same, strings are considered equal. In reality the string length is compared first, which is important both from implementation simplicity and from performance perspective.

Also please explain what does it mean that equals is consistent with compareTo (it might not be obvious). Finally the source code is poorly formatted.

Mike P(Okidoky) replied on Fri, 2012/11/23 - 10:40am

First, thank goodness that Java doesn't have operator overloading. You'd never be able to trust what you'd be looking at unless you'd constantly be brushing up on what the implementation does.

Hashcode could be used to quickly eliminate unequal strings. I think the upsides outweigh the downsides using hashcode (which can trigger a first-time calculation).

Last, the code visually looks like a horrid blob of goo. I'd have written it like this:The compiler and JVM ought to be able to optimize this to be as efficient as manually trying to grasp at trying to "cache" member fields, etc.

public boolean equals(Object obj) 
{
    if (this == obj) 
        return true;

    if (obj instanceof String) 
    {
        String str = (String)obj;

        if (count != str.count) 
            return false;

        if (hashCode() != str.hasCode())
            return false;

        for (int i = offset, j = strl.offset - i, k = offset + count; i < k; i++)
        {
            if (value[i] != str.value[i + j])
                return false;
        }

        return true;
    }
    return false;
}

And then my pet peeve is the awful K&R bracing style that Java developers use. Clearly, Alman style looks cleaner and you can browse up and down code and interpret it quicker and more efficiently. Saving vertical space should not be a motivation. I know this is a religious argument, but I can't for the life of me understand why people "like" K&R bracing style.

Stig Christensen replied on Sun, 2012/11/25 - 9:03am in response to: Mike P(Okidoky)

hasCode() would make it very expensive on large strings in many cases. 

I guess if you wanted the fast lookup you would have a HashSet or the like anyway.


Mike P(Okidoky) replied on Sun, 2012/11/25 - 10:57am in response to: Stig Christensen

No it wouldn't. The values are cached and requires walking through all the characters only once. Sets and Maps also invoke hashCode. That's the whole point of hash codes in the first place, a quick rough signature.

Stig Christensen replied on Sun, 2012/11/25 - 11:54am in response to: Mike P(Okidoky)

You misunderstand me - and I know the hash code is cached. 

In many cases you will not compare the same String many times, therefore hashCode() would be expensive. If you compare two very large Strings there is a good chance that equals() would return after the 1st char and that is fast! Hash would be slow.

If you do a lot of comparisons you would put them in a Hashset anyway, and String would then use the hashCode() as expected.

I think this is why String equals is written without hasCode(). It should not heart performance on a simple comparison.

Mike P(Okidoky) replied on Sun, 2012/11/25 - 12:32pm in response to: Stig Christensen

Actually, I just remembered something. A little while back, I was looking at improving both equals and compareTo. I had actually contemplated doing a hybrid comparison and hashCode generation.

But I although agree with that one should not trigger a hashCode on just an equals call, there are still ways to improve it. The hybrid generate while comparing maybe maybe not. But checking if a hashCode is available on both sides could work.

if (hash != 0 && anotherString.hash != 0 && hash != anotherString.hash) return false;

Could first compare first (few) characters to give a possible string inequality the change to conclude it's not equals before spending the time on hash comparison above.

Another option is to make some native code for it. System.arraycopy() has become native a while back. Perhaps System.arraycmp() might come in handy...
Wait... Arrays has public static boolean equals(char[] a, char[] a2)...
Doesn't accommodate an offset and isn't native...


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.