开发者

What is the most elegant way to convert a hyphen separated word (e.g. "do-some-stuff") to the lower camel-case variation (e.g. "doSomeStuff")?

What is the most elegant way to convert a hyphen separated word (e.g. "do-some-stuff") to the lower camel-case variation (e.g. "doSomeStuff") in 开发者_开发问答Java?


Use CaseFormat from Guava:

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

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


With Java 8 there is finally a one-liner:

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

Though it takes splitting over 3 actual lines to be legible ツ

(Note: "\\-" is for kebab-case as per question, for snake_case simply change to "_")


The following method should handle the task quite efficient in O(n). We just iterate over the characters of the xml method name, skip any '-' and capitalize chars if needed.

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


Why not try this:

  1. split on "-"
  2. uppercase each word, skipping the first
  3. join

EDIT: On second thoughts... While trying to implement this, I found out there is no simple way to join a list of strings in Java. Unless you use StringUtil from apache. So you will need to create a StringBuilder anyway and thus the algorithm is going to get a little ugly :(

CODE: Here is a sample of the above mentioned aproach. Could someone with a Java compiler (sorry, don't have one handy) test this? And benchmark it with other versions found here?

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
}


If you don't like to depend on a library you can use a combination of a regex and String.format. Use a regex to extract the starting characters after the -. Use these as input for String.format. A bit tricky, but works without a (explizit) loop ;).

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

}


Here is a slight variation of Andreas' answer that does more than the OP asked for:

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

It handles a few special cases:

  • fUnnY-cASe is converted to funnyCase
  • --dash-before-and--after- is converted to dashBeforeAndAfter
  • some.other$funky:chars? is converted to someOtherFunkyChars


For those who has com.fasterxml.jackson library in the project and don't want to add guava you can use the jaskson namingStrategy method:

new PropertyNamingStrategy.SnakeCaseStrategy.translate(String);


get The Apache commons jar for StringUtils. Then you can use the capitalize method

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


As I'm not a big fan of adding a library just for one method, I implemented my own solution (from camel case to snake case):

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

Needs to be adapted depending of the in / out cases.


In case you use Spring Framework, you can use provided StringUtils.

import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.stream.Collectors;

public class NormalizeUtils {

    private static final String DELIMITER = "_";    

    private NormalizeUtils() {
        throw new IllegalStateException("Do not init.");
    }

    /**
     * Take name like SOME_SNAKE_ALL and convert it to someSnakeAll
     */
    public static String fromSnakeToCamel(final String name) {
        if (StringUtils.isEmpty(name)) {
            return "";
        }

        final String allCapitalized = Arrays.stream(name.split(DELIMITER))
                .filter(c -> !StringUtils.isEmpty(c))
                .map(StringUtils::capitalize)
                .collect(Collectors.joining());

        return StringUtils.uncapitalize(allCapitalized);
    }
}


Iterate through the string. When you find a hypen, remove it, and capitalise the next letter.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜