2010-02-08 6 views
82

Я создал программу Java, чтобы сравнить две строки:Как сделать мой случай сравнения строк нечувствительным?

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

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

Он отображает "Добро пожаловать". Я понимаю, что он чувствителен к регистру. Но моя проблема в том, что я хочу сравнить две строки без чувствительности к регистру. То есть Я ожидаю, что выход будет hai.

+3

Если вы знаете, он чувствителен к регистру, можно преобразовать как в нижний регистр или верхний регистр перед сравнением. – fastcodejava

+0

, если вы используете 's1.equalsIgnoreCase (s2)', вы можете не делать этого везде, где это необходимо. Я предлагаю вам найти, откуда взялась строка - возможно, файл или база данных или пользовательский ввод - и конвертировать в верхний регистр (или в нижний регистр) и продолжать использовать .equals для сравнения. – H2ONaCl

+0

Не конвертируйте в нижний/верхний регистр (как предложено выше), используйте принятый подход 'equalsIgnoreCase'. Прочитайте проблему турецкого I и аналогичные проблемы Юникода для обоснования. –

ответ

140
  • Лучше всего было бы использовать s1.equalsIgnoreCase(s2): (см javadoc)
  • Вы можете также превратить их обоих в верхний/нижний регистр и использовать s1.equals(s2)
+34

Просто имейте в виду, что эти два решения не обязательно одинаковы для всех локалей. Строка # equalsIgnoreCase не использует языковые правила обсадной колонны, в то время как String # toLowerCase и #toUpperCase делают. – jarnbjo

+0

@jarnbjo Можете ли вы привести пример, где для этой разницы? – towi

+14

Режимы конкретных случаев на местном уровне, по крайней мере, реализуются для турецкого и немецкого языков. Турецкий лечит я с и без точки как две разные буквы, создавая пары нижних/верхних регистров iİ и ıI, в то время как другие языки рассматривают iI как пару и не используют буквы ı и İ. На немецком языке нижний регистр ß капитализируется как «SS». – jarnbjo

16

Вы должны использовать compareToIgnoreCase метод String объекта.

int compareValue = str1.compareToIgnoreCase(str2); 

if (compareValue == 0) это означает str1 равна str2.

+1

не знал, что этот метод также доступен. благодаря! –

2

Обратите внимание, что вы можете выполнить нулевые проверки на них, а также перед выполнением ваших .equals или .equalsIgnoreCase.

Объект 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

+0

Измененный код, который должен быть более чистым в соответствии с вышеприведенным комментарием - был длинный день :) – VeenarM

+1

Вы также можете изменить первую строку на 'if (str1 == str2) return true;', который оба обслуживает нули, а также сокращает время, когда два строки ссылаются на один и тот же строковый объект. – Barney

3

В умолчанию Java API в вас есть:

String.CASE_INSENSITIVE_ORDER 

Так что вам не нужно переписать компаратор, если вы должны были использовать строки с отсортированными структурами данных.

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

Это то, что вы хотите для чистых проверок равенства в своем собственном коде.

Просто для получения дополнительной информации обо всем, что касается равенства строк в Java. Функция хэш-код() класса java.lang.String «чувствителен к регистру»:

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 "будут считаться равными, тогда вам придется обернуть строку в другом классе (вы не можете расширять String, так как это окончательный класс).Например:

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>(); 
-5
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; 
} 
+2

Нечеткий и путаный ответ –

+0

и неправильный –

8
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

19

String.equalsIgnoreCase является наиболее практичным выбором для наивных прецедентного нечувствительное сравнение строк.

Однако полезно помнить, что этот метод не делает полного сгибания или декомпозиции корпуса, поэтому не может выполнять сопоставление без использования материалов, как указано в стандарте Unicode. Фактически, API-интерфейсы JDK не предоставляют доступ к информации о символьных данных фальцовки, поэтому это задание лучше всего делегировать проверенной и проверенной сторонней библиотеке.

Эта библиотека 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 на прописные или нижний регистр строк провалится даже этот простой тест.

(Do внимания, однако, что предопределенный случай складного вкуса getNFKCCasefoldInstance локал-независимо. Турецкие районы немного больше работы, связанную с UCharacter.foldCase может быть необходима)

-1

Чтобы быть nullsafe, вы можете использовать

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

или

org.apache.commons.lang3.StringUtils.equalsIgnoreCase(CharSequence, CharSequence) 
Смежные вопросы