문자열 비교에서 대소 문자를 구분하지 않게하려면 어떻게해야합니까?


111

두 문자열을 비교하는 Java 프로그램을 만들었습니다.

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

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

"환영"이 표시됩니다. 대소 문자를 구분한다는 것을 이해합니다. 하지만 내 문제는 대소 문자를 구분하지 않고 두 문자열을 비교하고 싶다는 것입니다. 즉, 출력이 hai.


3
대소 문자를 구분한다는 것을 알고 있다면 비교하기 전에 둘 다 소문자 또는 대문자로 변환 할 수 있습니다.
fastcodejava 2010

사용하는 경우 s1.equalsIgnoreCase(s2)수행해야 할 모든 곳에서 수행하지 못할 수 있습니다. 문자열의 출처 (파일 또는 데이터베이스 또는 사용자 입력)를 찾아 대문자 (또는 소문자)로 변환하고 비교를 위해 .equals를 계속 사용하는 것이 좋습니다.
H2ONaCl

2
위의 주석에서 제안한대로 소문자 / 대문자로 변환하지 말고 허용 된 equalsIgnoreCase접근 방식을 사용하십시오 . 근거를 위해 터키어 I 문제 및 유사한 유니 코드 문제를 읽어보십시오.
Ohad Schneider

1
@OhadSchneider equalsIgnoreCase는 "i"와 "I"를 비교할 때 true를 반환하기 때문에 터키어에 대해 잘못된 값을 반환하지만 false를 반환해야합니다. 따라서 로케일을 고려하고 싶다면 Collator실제로 a 가 갈 길이라고 생각합니다.
Trejkaz

1
@OhadSchneider 궁금합니다. 문자 단위로 수행하면 동일한 결과가 생성되지만 전체 문자열에 대해 toLowerCase/ toUpperCase수행하고 문자 단위로 수행하면 두 가지 다른 결과가 제공됩니다.
Trejkaz

답변:


171
  • 가장 좋은 방법은 다음을 사용하는 것입니다 s1.equalsIgnoreCase(s2). ( javadoc 참조 )
  • 둘 다 대 / 소문자로 변환하여 사용할 수도 있습니다. s1.equals(s2)

39
두 솔루션이 모든 로케일에 대해 반드시 동일하지는 않다는 점에 유의하십시오. String # equalsIgnoreCase는 로케일 특정 대 / 소문자 규칙을 사용하지 않는 반면 String # toLowerCase 및 #toUpperCase는 사용합니다.
jarnbjo 2010

1
@jarnbjo 그 차이에 대한 예를 들어 줄 수 있습니까?
towi

16
로케일 특정 케이스 규칙은 적어도 터키어 및 독일어에 대해 구현됩니다. 터키어는 점이 있거나없는 I를 두 개의 다른 문자로 취급하여 소문자 / 대문자 쌍 iİ 및 ıI를 생성하는 반면 다른 언어는 iI를 쌍으로 취급하고 문자 ı 및 İ를 사용하지 않습니다. 독일어에서 소문자 ß는 "SS"로 대문자로 표시됩니다.
jarnbjo


24

String.equalsIgnoreCase 대소 문자를 구분하지 않는 순진한 문자열 비교를위한 가장 실용적인 선택입니다.

그러나이 메서드는 전체 대 / 소문자 접기 나 분해를 수행하지 않으므로 유니 코드 표준에 지정된대로 대 / 소문자 없는 일치를 수행 할 수 없다는 점을 알아 두는 것이 좋습니다 . 실제로 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

따라서 Sorted 데이터 구조가있는 문자열을 사용하는 경우 비교기를 다시 작성할 필요가 없습니다.

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

자신의 코드에서 순수한 동등성 검사를 원하는 것입니다.

Java에서 Strings의 동등성과 관련된 모든 것에 대한 추가 정보입니다. 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
참고 : 두 번째 두 명령문을 결합하여 다음과 같은 결과를 얻을 수 있습니다 if (str1 == null || str2 == null) return false;..
LuckyMe

수정 된 코드는 위의 의견에 따라 청소기합니다 - :) 긴 날
VeenarM

1
또한 if (str1 == str2) return true;두 문자열 참조가 동일한 문자열 개체를 참조하는 경우 두 가지 모두 null을 제공 하는 첫 번째 줄을 변경할 수도 있습니다 .
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.