2014-10-30 2 views
9

Есть много-много примеров о том, почему и когда java.lang.String.equalsIgnoreCase потерпит неудачу из-за неправильного использования языкового стандарта.Какая правильная альтернатива Java equalsIgnoreCase?

Но я не нашел примеров правильного пути. В отличие от java.lang.String.toUpperCase нет версии с параметром locale. Преобразование обеих строк в верхний или нижний регистр представляется бесполезным. Особенно, когда вы работаете над приложением, проводящим множество сравнений.

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

+1

Возможно, с помощью ['Collator'] (http://docs.oracle.com/javase/8/docs/api/java/text/Collator.html)? – fge

+2

Не могли бы вы изменить свой вопрос с примерами неправильных результатов '.equalsIgnoreCase()'? Мне очень любопытно ... – fge

+0

@fge Турецкий «i» и немецкий «ß» кажутся наиболее цитируемыми неудачами. Но вы правы, я добавлю несколько примеров позже. – Martin

ответ

1

Согласно this page, вы можете использовать Collator сделать регистрозависимости равенство следующим образом:

//retrieve the runtime user's locale 
Locale locale = new Locale(getUserLocale()); 

//pass the user's locale as an argument 
Collator myCollator = Collator.getInstance(locale); 

//set collator to Ignore case but not accents 
//(default is Collator.TERTIARY, which is 
//case sensitive) 
myCollator.setStrength(Collator.SECONDARY); 

int i = myCollator.compare(stringA,stringB); 

(Скопировано из вышеприведенного сайта ...)

Очевидно, что в других контекстах вы можете выбрать locale по-разному.


Для @fge - этот отчет Oracle Bug Report дает пример того, что происходит.

+0

Спасибо за пример! И для того, чтобы найти время, чтобы найти код ... – fge

0

Возможной альтернативой может быть злоупотребление Regex. Это вполне производительность ресурсоемких с динамически меняющимися строками, но если вы сравниваете против констант может быть альтернативой:

Matcher matcher = Pattern.compile("^" + myOtherString + "$", 
    Pattern.CASE_INSENSITIVE | Pattern.LITERAL | Pattern.UNICODE_CASE).matcher(); 
if (matcher.matches(myString)) { 
    // ... 
} 

Это анкеры строка, которую вы хотите сравнить против, указывает Юникод не чувствительны к регистру соответствие строки Literal.

+0

Я предсказываю, что будет иметь ту же проблему, что и при использовании 'String.equalsIgnoreCase'. Сравнение должно быть локальным, а не только Unicode. ('String.equalsIgnoreCase' также поддерживает Unicode ... в соответствии с' String' javadocs.) –

+0

@StephenC классная часть об этом заключается в том, что в приведенной в ответе редакции не будет той же проблемы. Задача ß -> SS исходит из того факта, что нет верхнего прописного эквивалента ß. только ß будет соответствовать ß и ss будет ** не ** соответствовать ß (как это происходит в equalsIgnoreCase();) – Vogel612