文字列比較で大文字と小文字を区別しないようにするにはどうすればよいですか?


111

2つの文字列を比較するJavaプログラムを作成しました。

String s1 = "Hello";
String s2 = "hello";

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

「ようこそ」と表示されます。大文字と小文字が区別されることを理解しています。しかし、私の問題は、大文字と小文字を区別せずに2つの文字列を比較したいことです。つまり、出力が期待されますhai


3
大文字と小文字が区別されることがわかっている場合は、比較する前に両方を小文字または大文字に変換できます。
fastcodejava

使用s1.equalsIgnoreCase(s2)すると、必要なすべての場所で失敗する可能性があります。文字列がどこから来たのかを見つけてください-おそらくファイルまたはデータベースまたはユーザー入力-そして大文字(または小文字)に変換し、比較のために.equalsを使い続けます。
H2ONaCl 2016

2
(上記のコメントで示唆されているように)小文字/大文字に変換しないでくださいequalsIgnoreCase。受け入れられているアプローチを使用してください。トルコ語のI問題と、その根拠となる類似のUnicode問題について読んでください。
Ohad Schneider

1
@OhadSchneider equalsIgnoreCaseは、 "i"と "I"を比較するとtrueを返すため、falseを返す必要があるにもかかわらず、トルコ語に対して誤った値を返します。したがって、ロケールを考慮に入れたい場合Collatorは、実際にはaを使用する方法だと思います。
Trejkaz 2018年

1
@OhadSchneiderなるほど。文字ごとに行うと同じ結果が得られるが、文字列全体に対してtoLowerCase/を実行toUpperCaseし、文字ごとに行うと、2つの異なる結果が得られると記載されています。
Trejkaz 2018年

回答:


171
  • 最高の使用法s1.equalsIgnoreCase(s2):(javadocを参照)
  • 大文字と小文字の両方に変換して使用することもできます s1.equals(s2)

39
2つのソリューションがすべてのロケールで同じであるとは限らないことに注意してください。String#equalsIgnoreCaseはロケール固有の大文字と小文字の規則を使用していませんが、String#toLowerCaseと#toUpperCaseは使用しています。
jarnbjo

1
@jarnbjoその違いの例を挙げていただけますか?
towi 2013年

16
ロケール固有のケースルールは、少なくともトルコ語とドイツ語で実装されています。トルコ語では、ドットありとドットなしのIを2つの異なる文字として扱い、小文字と大文字のペアiİとıIを作成しますが、他の言語ではiIをペアとして扱い、文字ıとİを使用しません。ドイツ語では、小文字のßは「SS」として大文字になります。
jarnbjo 2013年


24

String.equalsIgnoreCase 単純な大文字と小文字を区別しない文字列比較の最も実用的な選択です。

ただし、このメソッドは完全な大文字小文字の変換も分解も行わないため、Unicode標準で指定されているように大文字と小文字を区別しないマッチングを実行できないことに注意してください実際、JDK APIは大文字小文字変換の文字データに関する情報へのアクセスを提供しないため、このジョブは、実証済みのテスト済みのサードパーティライブラリに委任するのが最適です。

そのライブラリはICUであり、大文字と小文字を区別しない文字列比較のためのユーティリティを実装する方法は次のとおりです。

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);

との単純な比較String.equalsIgnoreCase、またはString.equals大文字または小文字の文字列での単純比較は、この単純なテストでも失敗します。

(ただし、事前定義された大文字と小文字の折りたたみフレーバーgetNFKCCasefoldInstanceはロケールに依存しないことに注意してください。トルコ語のロケールの場合は、もう少し作業UCharacter.foldCaseが必要になる場合があります。)


22

オブジェクトのcompareToIgnoreCaseメソッドを使用する必要がありStringます。

int compareValue = str1.compareToIgnoreCase(str2);

if (compareValue == 0)str1等しいことを意味しstr2ます。


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");
}

これで出力されます: hai


5

デフォルトのJava APIには次のものがあります。

String.CASE_INSENSITIVE_ORDER

そのため、ソートされたデータ構造で文字列を使用する場合は、コンパレータを書き直す必要はありません。

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

独自のコードで純粋な等価チェックに必要なものです。

Javaでの文字列の等価性に関するあらゆる情報を提供します。java.lang.StringクラスのhashCode()関数は「大文字と小文字が区別されます」:

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;
}

したがって、キーとして文字列を含むHashtable / HashMapを使用し、「SomeKey」、「SOMEKEY」、「somekey」などのキーが等しいと見なされるようにするには、文字列を別のクラスでラップする必要があります(拡張できません最終クラスなので文字列)。例えば ​​:

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;
    }
}

そしてそれをそのまま使用します:

HashMap<HashWrap, Object> map = new HashMap<HashWrap, Object>();

2

.equalsまたは.equalsIgnoreCaseを実行する前に、それらに対してnullチェックを実行することもできます。

null Stringオブジェクトは、equalsメソッドを呼び出すことができません。

つまり:

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);
}

1
注:2番目の2つのステートメントを組み合わせて、次のような同じ結果を生成できますif (str1 == null || str2 == null) return false;
LuckyMe 2013

上記のコメントに従って、コードをより
明確に

1
また、if (str1 == str2) return true;両方がnullに対応する最初の行を変更し、2つの文字列参照が同じ文字列オブジェクトを参照する場合のショートカットを変更することもできます。
Barney




1

nullsafeにするためには、

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

または

org.apache.commons.lang3.StringUtils.equalsIgnoreCase(CharSequence, CharSequence)

-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;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.