Java: String: equalsIgnoreCase vs switching everything to Upper/Lower Case

59,826

Solution 1

Use equalsIgnoreCase because it's more readable than converting both Strings to uppercase before a comparison. Readability trumps micro-optimization.

What's more readable?

if (myString.toUpperCase().equals(myOtherString.toUpperCase())) {

or

if (myString.equalsIgnoreCase(myOtherString)) {

I think we can all agree that equalsIgnoreCase is more readable.

Solution 2

equalsIgnoreCase avoids problems regarding Locale-specific differences (e.g. in Turkish Locale there are two different uppercase "i" letters). On the other hand, Maps only use the equals() method.

Solution 3

But the issue in the latter, where you make an assumption that either upper or lower case is passed, you cannot blindly trust the caller. So you have to include an ASSERT statement at the start of the method to make sure that the input is always in the case your are expecting.

Solution 4

Neither is better, they both have their uses in different scenarios.

Many times when you have to do string comparisons there is the opportunity to massage at least one of the strings to make it easier to compare, and in these cases you will see strings converted to a particular case, trimmed, etc before being compared.

If, on the other hand, you just want to do an on-the-fly case-insensitive comparison of two strings then feel free to use equalsIgnoreCase, that's what its there for after all. I would caution, however, that if you're seeing a lot of equalsIgnoreCase it could be a code smell.

Solution 5

equalsIgnoreCase documentation in jdk 8

  • Compares this String to another String, ignoring case considerations. Two strings are considered equal ignoring case if they are of the same length and corresponding characters in the two strings are equal ignoring case.

    Two characters c1 and c2 are considered the same ignoring case if at least one of the following is true:

    • The two characters are the same (as compared by the == operator)
    • Applying the method java.lang.CharactertoUpperCase(char)to each character produces the same result
    • Applying the method java.lang.CharactertoLowerCase(char) to each character produces the same result

My thoughts:

So using equalsIgnoreCase we iterate through the Strings (only if their size values are the same) comparing each char. In the worst case, we will performance will be O( 3cn ) where n = the size of your strings. We will use no extra space.

Using toUpper() then comparing if the strings are equal, you ALWAYS loop through each string one time, converting all strings to upper, then do an equivalence by reference check (equals()). This is theta(2n + c). But just remember, when you do toUpperCase(), you actually have to create two new Strings because Strings in Java are immutable.

So I would say that equalsIgnoreCase is both more efficient and easier to read.

Again I would consider the use case, because that would be what it comes down to for me. The toUpper approach could be valid in certain use cases, but 98% of the time I use equalsIgnoreCase().

Share:
59,826

Related videos on Youtube

Jason Rogers
Author by

Jason Rogers

Updated on July 09, 2022

Comments

  • Jason Rogers
    Jason Rogers almost 2 years

    It came to my attention that there a several ways to compare strings in Java.

    I just got in the habit ages ago to use equalsIgnoreCase to avoid having problems with case sensitive strings.

    Others on the other hand prefer passing everything in upper or lower case.

    From where I stand (even if technically I'm sitting), I don't see a real difference.

    Does anybody know if one practice is better than the other? And if so why?

  • Asaph
    Asaph over 13 years
    I think you meant "caller", not "callee". Right?
  • CurtainDog
    CurtainDog over 13 years
    Yes but... this is a little bit of a straw man. If you're working with strings where the case doesn't matter then chances are you would've prepped the strings long before the comparison. Say you are matching a user entered word against a dictionary. You'd have the dictionary in a particular case and you'd convert the user string once.
  • Falmarri
    Falmarri over 13 years
    Was this supposed to be a comment to asaph?
  • Asaph
    Asaph over 13 years
    @CurtainDog: If you're searching a dictionary, surely you don't want to use equals or equalsIgnoreCase at all. Doing so kind of implies that you're looping through items in the dictionary which wouldn't perform well. Wouldn't you rather use a more suitable data structure like a HashMap?
  • CurtainDog
    CurtainDog over 13 years
    Don't think you can get away from using equals if you have a HashMap ;) But you are right, the second form is more readable, it's just that (1) I don't see the first form (as written) in the wild much; and (2) there is a place for both forms (where the first form would be comparing strings that have already been prepared for comparison)
  • Asaph
    Asaph over 13 years
    @CurtainDog: If you have a dictionary of words (keys) and definitions (values) in a HashMap, you use HashMap.get(Object key) to retrieve an item from the dictionary. No need for equals. Maybe the JVM uses equals under the hood to resolve collisions in the HashMap but that's all transparent to the high level programmer.
  • Lambart
    Lambart over 11 years
    That post does not actually cite any real performance tests, and incorrectly states that "equalsIgnoreCase function uses toLowerCase function internally", which is not true at least for OpenJDK 6.
  • Dennie
    Dennie over 9 years
    I looked this up in the OpenJDK source to make sure, as javadoc does not seem to mention locales. The method compares the strings char by char. If two chars are not the same in upper case, they are compared in lower case which is apparently needed for the Georgian alphabet. This makes equalsIgnoreCase slightly less performant, but more correct.
  • Adam
    Adam almost 9 years
    so when converting from lower case to upper case in Turkish, how does one deal with the choice?
  • Victor Zamanian
    Victor Zamanian almost 8 years
    @Asaph still, equals is used, which was the point of that remark so long ago.
  • Alican Balik
    Alican Balik about 6 years
    You need to specify Locale. e.g.: "turkish".toUpperCase(Locale.ENGLISH)
  • Jake Griffin
    Jake Griffin almost 6 years
    @koljaTM Yeah, there are two different uppercase "i" letters... but there are also two different lowercase "i" letters to go along with them, so I'm not sure how that's relevant. en.wikipedia.org/wiki/Turkish_alphabet
  • tresf
    tresf almost 3 years
    @JakeGriffin It's relevant because otherwise, it breaks.