2010-03-01 27 views
27

Angenommen zwei Java-String-Objekte:Verändert Java toLowerCase() die ursprüngliche Stringlänge?

String str = "<my string>"; 
String strLower = str.toLowerCase(); 

Ist es dann richtig, dass für jeden Wert von <my string> der Ausdruck

str.length() == strLower.length() 

zu true auswertet?

Also, behält String.toLowerCase() ursprünglichen String Länge für einen beliebigen Wert von String?

Antwort

41

Überraschenderweise tut es nicht !!

Von Java-Dokumentation von toLowerCase

Wandelt alle Zeichen in diesem String Fall zu senken, die Regeln des gegebenen Locale verwenden. Fallzuordnungen hängen stark von den Zeichendaten der Unicode-Spezifikation ab. Da Fallzuordnungen nicht immer 1: 1 Zeichenzuordnungen sind, kann der resultierende String eine andere Länge als der ursprüngliche String haben.

Beispiel:

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

Können Sie einige Beispiele nennen? Ich kenne mehrere Beispiele, die die obere Variante unterschiedlich groß machen würden als die untere, z. 'ß' würde' SS' werden, aber nicht umgekehrt. – BalusC

+10

+1: javadocs - so nah und doch so weit ... – MicSim

+7

@BalusC: Es gibt einige ausgefallene Regeln bezüglich der Kombination von Zeichen in den Gebietsschemas AZ, LT und TR, siehe 'java/lang/ConditionalSpecialCasing.java'. Beispiel: "" \ u00cc ".toLowerCase (neues Gebietsschema (" lt ")). Length() == 3' – axtavt

4

Zunächst einmal würde Ich mag darauf hinweisen, dass ich absolut mit der (zur Zeit am höchsten bewerteten) Antwort von @codaddict zustimmen.

Aber ich wollte, ein Experiment tun, so ist es hier:

Es ist kein formaler Beweis, aber dieser Code lief für mich, ohne jemals das Innere der 16 if (mit JDK 1.6.0-Update erreicht auf Ubuntu):

Edit: Hier einige aktualisierte Code, der Locales auch Griffe:

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

ausgeführt wird, der Code mit den locale Namen m In der angenommenen Antwort werden einige Beispiele gedruckt. Wenn Sie es ohne ein Argument ausführen, werden alle verfügbaren Gebietsschemata getestet (und das dauert eine ganze Weile!).

Es ist nicht umfangreich, weil theoretisch könnte Multi-Zeichen-Strings, die sich anders verhalten, aber es ist eine gute erste Annäherung.

Beachten Sie auch, dass viele der auf diese Weise erzeugten Zwei-Zeichen-Kombinationen wahrscheinlich UTF-16 ungültig sind, so dass die Tatsache, dass nichts in diesem Code explodiert, nur auf eine sehr robuste String-API in Java zurückzuführen ist.

Und last but not least: Selbst wenn die Annahme für die aktuelle Implementierung von Java zutrifft, kann dies leicht geändert werden, wenn zukünftige Versionen von Java zukünftige Versionen des Unicode-Standards implementieren, in denen die Regeln für neue Zeichen Situationen einführen können wo das nicht mehr gilt.

Also abhängig davon ist das immer noch eine ziemlich schlechte Idee.

+3

Sie sollten wissen, dass der Code, den Sie geschrieben haben, vom Standardgebietsschema abhängig ist. Nicht offensichtlich, aber gemein. –

2

Denken Sie auch daran, dass toUpperCase() auch nicht die Länge bewahrt. Beispiel: "straße" wird für das deutsche Gebietsschema "STRASSE". Sie sind also mehr oder weniger geschraubt, wenn Sie mit Groß- und Kleinschreibung Zeichenfolgen arbeiten und Sie den Index für etwas speichern müssen.

+0

Da sowohl Straße als auch Straße korrekte Schreibweisen sind (die Tatsache ignorierend, dass sie ein großes Anfangs-S haben sollten, weil sie Substantive sind), nehme ich an, dass es zu dem interessanten Nebeneffekt kommt, dass Groß- und Kleinschreibung zu einer anderen Zeichenkette führen ? Hast du es versucht? – Fredrik

Verwandte Themen