Ha toLowerCase di Java () preservare originale lunghezza della stringa?
-
23-09-2019 - |
Domanda
Si supponga due oggetti Java String:
String str = "<my string>";
String strLower = str.toLowerCase();
E 'quindi vero che per ogni valore di <my string>
l'espressione
str.length() == strLower.length()
viene valutato come true
?
Quindi, fa String.toLowerCase()
preservare la lunghezza della stringa originale per ogni valore di stringa?
Soluzione
A sorpresa lo fa non !!
Da documenti Java di toLowerCase
Converte tutti i personaggi di questa stringa in minuscolo utilizzando le regole della data Locale. mappatura caso è basata sulla versione standard Unicode specificato dalla classe di caratteri. Poiché caso mappature non sono sempre 1: 1 mapping char, la stringa risultante può essere una lunghezza diversa rispetto alla stringa originale
.
Esempio:
package com.stackoverflow.q2357315;
import java.util.Locale;
public class Test {
public static void main(String[] args) throws Exception {
Locale.setDefault(new Locale("lt"));
String s = "\u00cc";
System.out.println(s + " (" + s.length() + ")"); // Ì (1)
s = s.toLowerCase();
System.out.println(s + " (" + s.length() + ")"); // i̇̀ (3)
}
}
Altri suggerimenti
Prima di tutto, vorrei sottolineare che sono assolutamente d'accordo con la (attualmente più alto-rated) risposta @codaddict.
Ma ho voluto fare un esperimento, ecco che è:
Non è una prova formale, ma questo codice ha funzionato per me, senza mai raggiungere l'interno del if
(usando JDK 1.6.0 Aggiornamento 16 su Ubuntu):
Modifica Ecco un po 'di codice aggiornato che gestisce versioni locali così:
import java.util.Locale;
public class ToLowerTester {
public final Locale locale;
public ToLowerTester(final Locale locale) {
this.locale = locale;
}
public String findFirstStrangeTwoLetterCombination() {
char[] b = new char[2];
for (char c1 = 0; c1 < Character.MAX_VALUE; c1++) {
b[0] = c1;
for (char c2 = 0; c2 < Character.MAX_VALUE; c2++) {
b[1] = c2;
final String string = new String(b);
String lower = string.toLowerCase(locale);
if (string.length() != lower.length()) {
return string;
}
}
}
return null;
}
public static void main(final String[] args) {
Locale[] locales;
if (args.length != 0) {
locales = new Locale[args.length];
for (int i=0; i<args.length; i++) {
locales[i] = new Locale(args[i]);
}
} else {
locales = Locale.getAvailableLocales();
}
for (Locale locale : locales) {
System.out.println("Testing " + locale + "...");
String result = new ToLowerTester(locale).findFirstStrangeTwoLetterCombination();
if (result != null) {
String lower = result.toLowerCase(locale);
System.out.println("Found strange two letter combination for locale "
+ locale + ": <" + result + "> (" + result.length() + ") -> <"
+ lower + "> (" + lower.length() + ")");
}
}
}
}
L'esecuzione di codice che con i nomi delle versioni locali citati nella risposta accettata stamperà alcuni esempi. L'esecuzione senza un argomento cercherà tutti i locale disponibili (e prendere un po 'di tempo!).
E 'non molto ampio, perché in teoria ci potrebbero essere le stringhe multi-carattere che si comportano in modo diverso, ma è una buona prima approssimazione.
Si noti inoltre che molte delle combinazioni di due caratteri prodotte in questo modo sono probabilmente validi UTF-16, quindi il fatto che esplode Nessuna disposizione del presente codice può essere imputato solo su un robusto API String in Java.
E, ultimo ma non meno importante: anche se l'ipotesi è vera per l'attuale implementazione di Java, che può facilmente cambiare le versioni una volta future di Java implementano le future versioni dello standard Unicode, in cui le regole per i nuovi personaggi possono introdurre situazioni in cui questo non è più vale.
Quindi, a seconda questo è ancora una brutta idea.
Anche ricordare che toUpperCase () non mantiene la lunghezza sia. Esempio: “Strasse” diventa “strasse” per la versione locale tedesca. Così sei più o meno avvitata se si sta lavorando con le stringhe maiuscole e minuscole ed è necessario memorizzare l'indice di qualcosa.