118

I created a Java program to compare two strings:

String str = "Hello";

if (str.equals("hello")) {
    System.out.println("match");
} else {
    System.out.println("no match");
}

It's case-sensitive. How can I change it so that it's not?

Michael
  • 41,989
  • 11
  • 82
  • 128
user268018
  • 1,245
  • 2
  • 9
  • 7
  • 3
    If you know it is case sensitive, you could convert both to lowercase or uppercase before comparing. – fastcodejava Feb 08 '10 at 09:05
  • 1
    if you use `s1.equalsIgnoreCase(s2)` you might fail to do it everywhere it needs to be done. I suggest that you find where the string comes from -- a file or database or user input perhaps -- and convert to either uppercase (or lowercase) and continue to use .equals for the comparison. – H2ONaCl Dec 24 '16 at 06:57
  • 2
    Don't convert to lower/uppercase (as suggested by the comments above), use the accepted `equalsIgnoreCase` approach. Read up on the Turkish I problem and similar Unicode issues for the rationale. – Ohad Schneider Oct 28 '17 at 12:42
  • You should consider marking an answer as accepted. I'd suggest the first one that answered with `equalsIgnoreCase`. – Paul Rooney Jan 01 '18 at 22:08
  • 1
    @OhadSchneider `equalsIgnoreCase` returns the wrong value for Turkish anyway, because it returns true for comparing "i" and "I", even though it should return false. So I suspect that if you want to take locales into account, a `Collator` is actually the way to go. – Hakanai Oct 03 '18 at 02:28
  • @Trejkaz fair enough, it looks like `equalsIgnoreCase` is equivalent to `toLowerCase` / `toUpperCase` comparison anyway (https://docs.oracle.com/javase/9/docs/api/java/lang/String.html#equalsIgnoreCase-java.lang.String-). Looks like .NET did it better with the `StringComparison` enum (https://learn.microsoft.com/en-us/dotnet/api/system.stringcomparison?view=netframework-4.7.2). – Ohad Schneider Oct 03 '18 at 21:45
  • 1
    @OhadSchneider I wonder. It says that doing it per-character produces the same result, but doing `toLowerCase` / `toUpperCase` on the whole string and doing it per-character give two different results as well. – Hakanai Oct 04 '18 at 23:19
  • Side note. Your misspelling hi. Just saying. It's really spelled hi. – Orion Dec 19 '18 at 18:01

12 Answers12

188

The best way is to use str.equalsIgnoreCase("foo"). It's optimized specifically for this purpose.

You can also convert both strings to upper- or lowercase before comparing them with equals. This is a trick that's useful to remember for other languages which might not have an equivalent of equalsIgnoreCase.

str.toUpperCase().equals(str2.toUpperCase())

If you are using a non-Roman alphabet, take note of this part of the JavaDoc of equalsIgnoreCase which says

Note that this method does not take locale into account, and will result in unsatisfactory results for certain locales. The Collator class provides locale-sensitive comparison.

Michael
  • 41,989
  • 11
  • 82
  • 128
Michael Bavin
  • 3,944
  • 6
  • 31
  • 35
  • 42
    Just be aware that the two solutions are not necessarily identical for all locales. String#equalsIgnoreCase is not using locale specific casing rules, while String#toLowerCase and #toUpperCase do. – jarnbjo Feb 08 '10 at 09:48
  • 1
    @jarnbjo Can you give an example where for that difference? – towi May 21 '13 at 08:54
  • 18
    Locale specific case rules are at least implemented for Turkish and German. Turkish treat I with and without dot as two different letters, creating the lower/upper case pairs iİ and ıI while other languages treat iI as a pair and do not use the letters ı and İ. In German, the lower case ß is capitalized as "SS". – jarnbjo May 21 '13 at 12:24
49

Use String.equalsIgnoreCase().

Use the Java API reference to find answers like these:

https://docs.oracle.com/javase/1.5.0/docs/api/java/lang/String.html#equalsIgnoreCase(java.lang.String)

https://docs.oracle.com/javase/1.5.0/docs/api/

fospathi
  • 537
  • 1
  • 6
  • 7
Thirler
  • 20,239
  • 14
  • 63
  • 92
27

String.equalsIgnoreCase is the most practical choice for naive case-insensitive string comparison.

However, it is good to be aware that this method does neither do full case folding nor decomposition and so cannot perform caseless matching as specified in the Unicode standard. In fact, the JDK APIs do not provide access to information about case folding character data, so this job is best delegated to a tried and tested third-party library.

That library is ICU, and here is how one could implement a utility for case-insensitive string comparison:

import com.ibm.icu.text.Normalizer2;

// ...

public static boolean equalsIgnoreCase(CharSequence s, CharSequence t) {
    Normalizer2 normalizer = Normalizer2.getNFKCCasefoldInstance();
    return normalizer.normalize(s).equals(normalizer.normalize(t));
}
    String brook = "flu\u0308ßchen";
    String BROOK = "FLÜSSCHEN";

    assert equalsIgnoreCase(brook, BROOK);

Naive comparison with String.equalsIgnoreCase, or String.equals on upper- or lowercased strings will fail even this simple test.

(Do note though that the predefined case folding flavour getNFKCCasefoldInstance is locale-independent; for Turkish locales a little more work involving UCharacter.foldCase may be necessary.)

glts
  • 21,808
  • 12
  • 73
  • 94
23

You have to use the compareToIgnoreCase method of the String object.

int compareValue = str1.compareToIgnoreCase(str2);

if (compareValue == 0) it means str1 equals str2.

Neil
  • 54,642
  • 8
  • 60
  • 72
Aliti
  • 2,025
  • 2
  • 27
  • 39
10
import java.lang.String; //contains equalsIgnoreCase()
/*
*
*/
String s1 = "Hello";
String s2 = "hello";

if (s1.equalsIgnoreCase(s2)) {
System.out.println("hai");
} else {
System.out.println("welcome");
}

Now it will output : hai

KNU
  • 2,560
  • 5
  • 26
  • 39
5

In the default Java API you have:

String.CASE_INSENSITIVE_ORDER

So you do not need to rewrite a comparator if you were to use strings with Sorted data structures.

String s = "some text here";
s.equalsIgnoreCase("Some text here");

Is what you want for pure equality checks in your own code.

Just to further informations about anything pertaining to equality of Strings in Java. The hashCode() function of the java.lang.String class "is case sensitive":

public int hashCode() {
    int h = hash;
    if (h == 0 && value.length > 0) {
        char val[] = value;

        for (int i = 0; i < value.length; i++) {
            h = 31 * h + val[i];
        }
        hash = h;
    }
    return h;
}

So if you want to use an Hashtable/HashMap with Strings as keys, and have keys like "SomeKey", "SOMEKEY" and "somekey" be seen as equal, then you will have to wrap your string in another class (you cannot extend String since it is a final class). For example :

private static class HashWrap {
    private final String value;
    private final int hash;

    public String get() {
        return value;
    }

    private HashWrap(String value) {
        this.value = value;
        String lc = value.toLowerCase();
        this.hash = lc.hashCode();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o instanceof HashWrap) {
            HashWrap that = (HashWrap) o;
            return value.equalsIgnoreCase(that.value);
        } else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        return this.hash;
    }
}

and then use it as such:

HashMap<HashWrap, Object> map = new HashMap<HashWrap, Object>();
le-doude
  • 3,345
  • 2
  • 25
  • 55
2

Note that you may want to do null checks on them as well prior to doing your .equals or .equalsIgnoreCase.

A null String object can not call an equals method.

ie:

public boolean areStringsSame(String str1, String str2)
{
    if (str1 == null && str2 == null)
        return true;
    if (str1 == null || str2 == null)
        return false;

    return str1.equalsIgnoreCase(str2);
}
VeenarM
  • 1,263
  • 1
  • 10
  • 14
  • 1
    Note: second two statements can be combined to produce same result like this: `if (str1 == null || str2 == null) return false;`. – LuckyMe Jul 09 '13 at 09:10
  • Modified code to be cleaner as per above comment - was long day :) – VeenarM Jul 13 '13 at 23:45
  • 1
    You could also change the first line to `if (str1 == str2) return true;` which both caters for nulls and also shortcuts the case where the two string references refer to the same string object. – Barney Mar 27 '14 at 22:11
2

Use s1.equalsIgnoreCase(s2): https://docs.oracle.com/javase/1.5.0/docs/api/java/lang/String.html#equalsIgnoreCase(java.lang.String).

fospathi
  • 537
  • 1
  • 6
  • 7
1

You can use equalsIgnoreCase

codaddict
  • 445,704
  • 82
  • 492
  • 529
1

More about string can be found in String Class and String Tutorials

Gopi
  • 5,656
  • 22
  • 80
  • 146
1

To be nullsafe, you can use

org.apache.commons.lang.StringUtils.equalsIgnoreCase(String, String)

or

org.apache.commons.lang3.StringUtils.equalsIgnoreCase(CharSequence, CharSequence)
brandstaetter
  • 932
  • 3
  • 13
  • 30
-6
public boolean newEquals(String str1, String str2)
{
    int len = str1.length();
int len1 = str2.length();
if(len==len1)
{
    for(int i=0,j=0;i<str1.length();i++,j++)
    {
        if(str1.charAt(i)!=str2.charAt(j))
        return false;
    }`enter code here`
}
return true;
}