2014-10-30 11 views
9

Istnieje wiele przykładów na to, dlaczego i kiedy java.lang.String.equalsIgnoreCase zakończy się niepowodzeniem z powodu nieprawidłowego użycia ustawień narodowych.Jaka jest poprawna alternatywa dla Javy w równym stopniuIgnoreCase?

Ale nie znalazłem żadnych przykładów prawidłowego sposobu. W przeciwieństwie do java.lang.String.toUpperCase nie ma wersji z parametrem lokalizacji. Konwersja obu łańcuchów na wielkie lub małe litery wydaje się być nieekonomiczna. Zwłaszcza, gdy pracujesz nad aplikacją wykonującą wiele porównań.

Jaki jest prawidłowy sposób porównywania ciągów znaków ignorowanych, biorąc pod uwagę zarówno ustawienia regionalne, jak i wydajność?

+1

Może za pomocą ['Collator'] (http://docs.oracle.com/javase/8/docs/api/java/text/Collator.html)? – fge

+2

Czy mógłbyś edytować swoje pytanie z przykładami na złe wyniki '.equalsIgnoreCase()'? Jestem bardzo ciekawy ... – fge

+0

@fge Turecki «i» i niemiecki «ß» wydają się być najbardziej przytaczanymi niepowodzeniami. Ale masz rację, dodam kilka przykładów później. – Martin

Odpowiedz

1

Według this page, można użyć Collator zrobić wielkość liter ma znaczenie równości następująco:

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

(Skopiowane z powyższej witryny ...)

Oczywiście, w innych kontekstach może wybrać locale inaczej.


Dla @fge - Ten raport o błędzie Oracle podaje przykład tego, co się dzieje.

+0

Dzięki za przykład! I za poświęcenie czasu, aby rzeczywiście znaleźć kod ... – fge

0

Alternatywą może być nadużywanie wyrażenia regularnego. Jest to dość wydajność intensywnie z dynamicznie zmieniającymi się strun, ale jeśli porównać przeciwko stałych to mógłby być alternatywą:

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

to zakotwicza ciąg chcesz porównać przeciwko określa Unicode świadomi wielkości liter dopasowanie ciągu literałowego.

+0

Przewiduję, że będą mieć ten sam problem, co przy użyciu 'String.equalsIgnoreCase'. Porównanie musi być oparte na locale, a nie tylko na Unicode. ('String.equalsIgnoreCase' jest także znany z Unicode ... zgodnie z' String' javadocs.) –

+0

@ StephenC o tym, że ekwizyty podane w twojej odpowiedzi nie będą miały tego samego problemu. Problem ß -> SS wynika z faktu, że nie ma wielkich odpowiedników ß. tylko ß będzie pasować ß i ss będzie ** nie ** pasować ß (jak to się dzieje w equalsIgnoreCase();) – Vogel612