2010-09-01 4 views
38

Was ist die eleganteste Art, ein Bindestrich-getrenntes Wort (z. B. "do-some-stuff") in die niedrigere Camel-Case-Variante (z. B. "doSomeStuff") in Java zu konvertieren?Was ist die eleganteste Art, ein Bindestrich-getrenntes Wort (z. B. "Mach etwas") in die niedrigere Camel-Case-Variante (z. B. "doSomeStuff") zu konvertieren?

+0

WTH ist jedes Beispiel Antwort eine öffentliche statische Methode implementiert? Wenn dies eindeutig ein verstecktes Implementierungsdetail einer größeren Abstraktion sein soll. –

Antwort

72

Verwenden CaseFormat von Guava:

import static com.google.common.base.CaseFormat.*; 

String result = LOWER_HYPHEN.to(LOWER_CAMEL, "do-some-stuff"); 
+0

welcher ist LOWER_HYPHEN? "do-some-stuff" oder "do_some_stuff"? –

+1

[Ein Hypen ist '-'] (http://en.wikipedia.org/wiki/Hyphen). Aus diesem Grund ist "LOWER_HYPEN" ein "Do-irgendwas" (http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/base/CaseFormat.html#LOWER_HYPHEN). ["do_some_stuff" wäre "LOWER_UNDERSCORE"] (http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/base/CaseFormat.html#LOWER_UNDERSCORE). –

8

Warum nicht versuchen:

  1. Split auf "-"
  2. Groß jedes Wort, das erste
  3. beitreten

EDIT Überspringen: Auf den zweiten Gedanken ... Beim Versuch, dies zu implementieren, habe ich herausgefunden, dass es keine einfache Möglichkeit gibt, einer Liste von Strings in Java beizutreten. Es sei denn, Sie verwenden StringUtil von Apache. So benötigen Sie einen StringBuilder sowieso zu schaffen und damit der Algorithmus wird ein wenig hässlich :(

CODE bekommen. Hier ist ein Beispiel der oben erwähnten aproach Könnte jemand mit einem Java-Compiler (sorry, don ‚t ein handliches Test) dieses haben? und Benchmark mit anderen Versionen hier?

public static String toJavaMethodNameWithSplits(String xmlMethodName) 
{ 
    String[] words = xmlMethodName.split("-"); // split on "-" 
    StringBuilder nameBuilder = new StringBuilder(xmlMethodName.length()); 
    nameBuilder.append(words[0]); 
    for (int i = 1; i < words.length; i++) // skip first 
    { 
     nameBuilder.append(words[i].substring(0, 1).toUpperCase()); 
     nameBuilder.append(words[i].substring(1)); 
    } 
    return nameBuilder.toString(); // join 
} 
+1

Dies erzeugt eine Menge String-Objekte (~ 8 zusätzliche Strings + ein Array für das angegebene Beispiel). Dies könnte ein Problem sein, wenn Sie viele XML-Tags verarbeiten müssen. –

+1

Die JVM ist sehr gut für den Umgang mit vielen kurzlebigen Objekten, einschließlich Strings, ausgestattet. –

+0

Hmm .. ich denke, es gibt einige Lösungen, die besser funktionieren. – codevour

0

Iterate durch den Strang. Wenn Sie einen Bindestrich finden, entfernen Sie diese, und profitieren Sie den nächsten Buchstaben.

9

die Die folgende Methode sollte die Aufgabe in O (n) recht effizient behandeln, wir iterieren nur über t Die Zeichen des Namens der xml-Methode, überspringen Sie ein '-' und aktivieren Sie die Zeichen falls erforderlich.

public static String toJavaMethodName(String xmlmethodName) { 
    StringBuilder nameBuilder = new StringBuilder(xmlmethodName.length());  
    boolean capitalizeNextChar = false; 

    for (char c:xmlMethodName.toCharArray()) { 
    if (c == '-') { 
     capitalizeNextChar = true; 
     continue; 
    } 
    if (capitalizeNextChar) { 
     nameBuilder.append(Character.toUpperCase(c)); 
    } else { 
     nameBuilder.append(c); 
    } 
    capitalizeNextChar = false; 
    } 
    return nameBuilder.toString(); 
} 
+0

Warum das Char-Array, wenn Sie einfach charAt() verwenden können? –

+0

@ Thorbjörn - Ich bevorzuge nur die erweiterte for loop Ausdruck. Persönlicher Stil. Aber du hast Recht - nicht mit 'toCharArray()' sollte etwas schneller sein –

4

Hier ist eine leichte Variation von Andreas' answer, der mehr noch als die OP fragte nach:

public static String toJavaMethodName(final String nonJavaMethodName){ 
    final StringBuilder nameBuilder = new StringBuilder(); 
    boolean capitalizeNextChar = false; 
    boolean first = true; 

    for(int i = 0; i < nonJavaMethodName.length(); i++){ 
     final char c = nonJavaMethodName.charAt(i); 
     if(!Character.isLetterOrDigit(c)){ 
      if(!first){ 
       capitalizeNextChar = true; 
      } 
     } else{ 
      nameBuilder.append(capitalizeNextChar 
       ? Character.toUpperCase(c) 
       : Character.toLowerCase(c)); 
      capitalizeNextChar = false; 
      first = false; 
     } 
    } 
    return nameBuilder.toString(); 
} 

Es kann einige Sonderfälle behandelt:

  • fUnnY-cASe-funnyCase
  • --dash-before-and--after- umgewandelt wird dashBeforeAndAfter
  • some.other$funky:chars? umgewandelt wird someOtherFunkyChars
+0

Das ist eine sehr coole Lösung, danke. – codevour

6

umgewandelt Wenn Sie Sie eine Kombination aus einem regulären Ausdruck verwenden können, nicht auf einer Bibliothek gerne abhängen und String.format . Verwenden Sie eine Regex, um die Startzeichen nach der - zu extrahieren. Verwenden Sie diese als Eingabe für String.format. Ein bisschen schwierig, aber funktioniert ohne eine (explizit) Schleife;).

public class Test { 

    public static void main(String[] args) { 
     System.out.println(convert("do-some-stuff")); 
    } 

    private static String convert(String input) { 
     return String.format(input.replaceAll("\\-(.)", "%S"), input.replaceAll("[^-]*-(.)[^-]*", "$1-").split("-")); 
    } 

} 
+0

Können Sie erweitern, wie die zweite alle Ausdruck ersetzen "[^ -] * - (.) [^ -] *" funktioniert? – startoftext

2

erhalten Die Apache Commons Glas für StringUtils.Dann können Sie die Methode

import org.apache.commons.lang.StringUtils; 
public class MyClass{ 

    public String myMethod(String str) { 
     StringBuffer buff = new StringBuffer(); 

     String[] tokens = str.split("-"); 
     for (String i : tokens) { 
      buff.append(StringUtils.capitalize(i)); 
     } 

     return buff.toString(); 
    } 
} 
+0

Ich hatte keine Wahl, andere Bibliotheken zu importieren, aber Apache Commons ist ein gemeinsamer Faktor für alle Projekte. Ich wünsche, dass diese Antwort auch die meisten Stimmen erhält :) – tusar

1

Kapital verwenden, wie ich bin kein großer Fan von Bibliothek Hinzufügen nur für ein Verfahren, implementiert ich meine eigene Lösung (von Kamel Fall Schlange Fall):

public String toSnakeCase(String name) { 
    StringBuilder buffer = new StringBuilder(); 
    for(int i = 0; i < name.length(); i++) { 
     if(Character.isUpperCase(name.charAt(i))) { 
      if(i > 0) { 
       buffer.append('_'); 
      } 
      buffer.append(Character.toLowerCase(name.charAt(i))); 
     } else { 
      buffer.append(name.charAt(i)); 
     } 
    } 
    return buffer.toString(); 
} 

Muss abhängig von den Ein-/Ausgangsfällen angepasst werden.

+2

Noch nützlich für mich, auch wenn es das Gegenteil der gestellten Frage ist. :) – pdem

8

Mit Java gibt es endlich einen Einzeiler:

Arrays.stream(name.split("\\-")) 
    .map(String::toLowerCase) 
    .map(s -> s.substring(0, 1).toUpperCase() + s.substring(1)) 
    .collect(Collectors.joining()); 

Obwohl es Aufspaltung über 4 tatsächlichen Linien nimmt lesbar sein ツ

(Anmerkung: "\\-" für ist Kebab-Fall nach Frage, für snake_case einfach auf "_" wechseln)

0

Für diejenigen, die com.fasterxml.jackson hat wollen Bibliothek im Projekt und nicht Guave fügen Sie die jaskson namingStrategy Methode verwenden können:

new PropertyNamingStrategy.SnakeCaseStrategy.translate(String); 
Verwandte Themen