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")?

Java

Java Problem Overview


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?

Java Solutions


Solution 1 - Java

Use CaseFormat from Guava:

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

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

Solution 2 - Java

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 "_")

Solution 3 - Java

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

Solution 4 - Java

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
}

Solution 5 - Java

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

}

Solution 6 - Java

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

Solution 7 - Java

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

Solution 8 - Java

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

Solution 9 - Java

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.

Solution 10 - Java

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

Solution 11 - Java

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionChristopher KlewesView Question on Stackoverflow
Solution 1 - JavaJoachim SauerView Answer on Stackoverflow
Solution 2 - JavaearcamView Answer on Stackoverflow
Solution 3 - JavaAndreas DolkView Answer on Stackoverflow
Solution 4 - JavaDaren ThomasView Answer on Stackoverflow
Solution 5 - JavaArne DeutschView Answer on Stackoverflow
Solution 6 - JavaSean Patrick FloydView Answer on Stackoverflow
Solution 7 - JavaChi DovView Answer on Stackoverflow
Solution 8 - JavaSeanView Answer on Stackoverflow
Solution 9 - JavaPierre LeméeView Answer on Stackoverflow
Solution 10 - JavagrellenortView Answer on Stackoverflow
Solution 11 - JavaNoel MView Answer on Stackoverflow