173 Stimmen

Was ist der einfachste Weg, um einen Java-String von Großbuchstaben (Wörter durch Unterstriche getrennt) in CamelCase (ohne Worttrennzeichen) umzuwandeln?

Der Titel sagt im Grunde alles aus. Wie kann ich in Java auf einfachste / eleganteste Weise einen String im Format "THIS_IS_AN_EXAMPLE_STRING" in das Format "ThisIsAnExampleString" umwandeln? Ich denke, es muss mindestens eine Möglichkeit geben, dies mit String.replaceAll() und einem Regex zu tun.

Meine ersten Gedanken sind: Den String mit einem Unterstrich (_) versehen, den gesamten String in Kleinbuchstaben umwandeln und dann replaceAll verwenden, um jedes Zeichen, das von einem Unterstrich gefolgt wird, in seine Großschreibungsform umzuwandeln.

10voto

Mike Punkte 1350

Java 1.8 Beispiel mit Streams

String text = "THIS_IS_SOME_TEXT";

String bactrianCamel = Stream.of(text.split("[^a-zA-Z0-9]"))
        .map(v -> v.substring(0, 1).toUpperCase() + v.substring(1).toLowerCase())
        .collect(Collectors.joining());
String dromedaryCamel = bactrianCamel.toLowerCase().substring(0, 1) + bactrianCamel.substring(1); 

System.out.printf("%s ist jetzt %s%n", text, dromedaryCamel); 

THIS_IS_SOME_TEXT ist jetzt thisIsSomeText

9voto

Yishai Punkte 87548
public static void main(String[] args) {
    String start = "DAS_IST_EIN_TEST";
    StringBuffer sb = new StringBuffer();
    for (String s : start.split("_")) {
        sb.append(Character.toUpperCase(s.charAt(0)));
        if (s.length() > 1) {
            sb.append(s.substring(1, s.length()).toLowerCase());
        }
    }
    System.out.println(sb);
}

3voto

Jacob van Lingen Punkte 8247

Das Apache Commons-Projekt hat jetzt die CaseUtils-Klasse, die eine toCamelCase-Methode hat, die genau das tut, was der/die OP gefragt hat:

 CaseUtils.toCamelCase("THIS_IS_AN_EXAMPLE_STRING", true, '_');

2voto

Srisa Punkte 959
public String withChars(String inputa) {
    String input = inputa.toLowerCase();
    StringBuilder sb = new StringBuilder();
    final char delim = '_';
    char value;
    boolean capitalize = false;
    for (int i=0; i

`Zeiten: in Millisekunden.

Iterationen = 1000
WithChars: start = 1379685214671 end = 1379685214683 diff = 12
WithRegex: start = 1379685214683 end = 1379685214712 diff = 29

Iterationen = 1000
WithChars: start = 1379685217033 end = 1379685217045 diff = 12
WithRegex: start = 1379685217045 end = 1379685217077 diff = 32

Iterationen = 1000
WithChars: start = 1379685218643 end = 1379685218654 diff = 11
WithRegex: start = 1379685218655 end = 1379685218684 diff = 29

Iterationen = 1000000
WithChars: start = 1379685232767 end = 1379685232968 diff = 201
WithRegex: start = 1379685232968 end = 1379685233649 diff = 681

Iterationen = 1000000
WithChars: start = 1379685237220 end = 1379685237419 diff = 199
WithRegex: start = 1379685237419 end = 1379685238088 diff = 669

Iterationen = 1000000
WithChars: start = 1379685239690 end = 1379685239889 diff = 199
WithRegex: start = 1379685239890 end = 1379685240585 diff = 695

Iterationen = 1000000000
WithChars: start = 1379685267523 end = 1379685397604 diff = 130081
WithRegex: start = 1379685397605 end = 1379685850582 diff = 452977`

2voto

leorleor Punkte 546

Nicht sicher, aber ich denke, ich kann weniger Speicher verwenden und eine zuverlässige Leistung erzielen, indem ich es charakterweise mache. Ich habe etwas Ähnliches gemacht, aber in Schleifen in Hintergrundthreads, also versuche ich das jetzt. Ich habe die Erfahrung gemacht, dass String.split teurer als erwartet ist. Und ich arbeite an Android und erwarte, dass GC-Aussetzer eher ein Problem sind als die CPU-Nutzung.

  public static String toCamelCase(String value) {
    StringBuilder sb = new StringBuilder();

    final char delimChar = '_';
    boolean lower = false;
    for (int charInd = 0; charInd < value.length(); ++charInd) {
      final char valueChar = value.charAt(charInd);
      if (valueChar == delimChar) {
        lower = false;
      } else if (lower) {
        sb.append(Character.toLowerCase(valueChar));
      } else {
        sb.append(Character.toUpperCase(valueChar));
        lower = true;
      }
    }

    return sb.toString();
  }

Ein Hinweis, dass String.split teuer ist, ist, dass der Eingabe ein Regex ist (nicht ein char wie bei String.indexOf) und es ein Array zurückgibt (anstatt eines Iterators, da die Schleife immer nur eine Sache gleichzeitig verwendet). Außerdem brechen Fälle wie "AB_AB_AB_AB_AB_AB..." die Effizienz jedes Massenkopien, und für lange Zeichenfolgen wird eine Größenordnung mehr Speicher als die Eingabezeichenfolge verwendet.

Das Durchlaufen von Zeichen hat keinen kanonischen Fall. Also erscheint mir der Overhead eines unnötigen Regex und Arrays im Allgemeinen weniger wünschenswert (als die Möglichkeit, die Effizienz der Massenkopie aufzugeben). Interessiert daran, Meinungen/Korrekturen zu hören, danke.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X