ti-enxame.com

Qual é a maneira mais elegante de converter um Word separado por hífen (por exemplo, "do-some-stuff") para a menor variação de caixa de camelo (por exemplo, "doSomeStuff")?

Qual é a maneira mais elegante de converter um Word separado por hífen (por exemplo, "do-some-stuff") para a menor variação de caixa de camelo (por exemplo, "doSomeStuff") em Java?

48
Christopher Klewes

Use CaseFormat de Goiaba :

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

String result = LOWER_HYPHEN.to(LOWER_CAMEL, "do-some-stuff");
85
Joachim Sauer

Com Java 8, finalmente existe um one-liner :

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

Embora seja necessário dividir mais de 3 linhas reais para ficar legível ツ

(Nota: "\\-" é para kebab-case conforme a pergunta, para snake_case simplesmente mude para "_")

12
earcam

O método a seguir deve lidar com a tarefa bastante eficiente em O (n). Nós apenas iteramos os caracteres do nome do método xml, ignoramos qualquer '-' e colocamos em maiúscula os caracteres, se necessário.

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();
}
9
Andreas_D

Por que não tentar isso:

  1. dividir em "-"
  2. maiúsculas cada palavra, pulando a primeira
  3. junte-se

EDIT : Pensando bem ... Enquanto tentava implementar isso, descobri que não havia uma maneira simples de ingressar em uma lista de strings em Java. A menos que você use StringUtil do Apache. Então, você precisará criar um StringBuilder de qualquer maneira e, assim, o algoritmo ficará um pouco feio :(

CÓDIGO : Aqui está um exemplo da abordagem acima mencionada. Alguém com um Java (desculpe, não tem um útil) pode testar isso? E compará-lo com outras versões encontradas aqui?

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
}
8
Daren Thomas

Se você não gosta de depender de uma biblioteca, pode usar uma combinação de uma expressão regular e String.format. Use um regex para extrair os caracteres iniciais após o -. Use-os como entrada para String.format. Um pouco complicado, mas funciona sem um loop (explizit);).

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

}
6
Arne Deutsch

Aqui está uma pequena variação de resposta de Andreas que faz mais do que o OP pediu:

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

Ele lida com alguns casos especiais:

  • fUnnY-cASe é convertido em funnyCase
  • --dash-before-and--after- é convertido em dashBeforeAndAfter
  • some.other$funky:chars? é convertido em someOtherFunkyChars
4
Sean Patrick Floyd

obtenha o jar comum do Apache para StringUtils. Então você pode usar o método de capitalização

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();
    }
}
2
Sean

Para quem tem a biblioteca com.fasterxml.jackson no projeto e não deseja adicionar goiaba, pode usar o método jaskson namingStrategy:

new PropertyNamingStrategy.SnakeCaseStrategy.translate(String);
2
Chi Dov

Como não sou muito fã de adicionar uma biblioteca apenas para um método, implementei minha própria solução (do caso camel ao caso cobra):

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

Precisa ser adaptado, dependendo dos casos de entrada/saída.

2
Pierre Lemée

Iterar através da cadeia. Quando encontrar um hífen, remova-o e coloque a próxima letra em maiúscula.

0
Noel M