181

The title pretty much says it all. What's the simplest/most elegant way that I can convert, in Java, a string from the format "THIS_IS_AN_EXAMPLE_STRING" to the format "ThisIsAnExampleString"? I figure there must be at least one way to do it using String.replaceAll() and a regex.

My initial thoughts are: prepend the string with an underscore (_), convert the whole string to lower case, and then use replaceAll to convert every character preceded by an underscore with its uppercase version.

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • 12
    Editor's note, 2015-03: the "initial thoughts" above are super dumb. You learn a lot about building software in six years. – Matt Ball Mar 20 '15 at 14:12
  • 4
    That moment when you ask 'what idiot wrote this' and look in source control to find that young, stupid you did. Been there, done that. – pierus Dec 04 '15 at 16:20
  • @MattBall: I like the initial thoughts version, it doesn't require a library and just needs a string concatenation and two regex replacements. – Konrad Höffner Jun 13 '19 at 14:14

22 Answers22

229

Another option is using Google Guava's com.google.common.base.CaseFormat

George Hawkins left a comment with this example of usage:

CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, "THIS_IS_AN_EXAMPLE_STRING");
Community
  • 1
  • 1
Arnout Engelen
  • 6,709
  • 1
  • 25
  • 36
144

Take a look at WordUtils in the Apache Commons lang library:

Specifically, the capitalizeFully(String str, char[] delimiters) method should do the job:

String blah = "LORD_OF_THE_RINGS";
assertEquals("LordOfTheRings", WordUtils.capitalizeFully(blah, '_').replaceAll("_", ""));

Green bar!

schemacs
  • 2,783
  • 8
  • 35
  • 53
Dan Gravell
  • 7,855
  • 7
  • 41
  • 64
  • 65
    No sir! We should rewrite these existing, already-working utilities ourselves, for we are proper programmers! – skaffman Jul 17 '09 at 15:41
  • 34
    It's 16:42 on a Friday afternoon. I'll let everyone else rewrite it, I'm going out for a beer \o/ ;) – Dan Gravell Jul 17 '09 at 15:43
  • 1
    More to the point, I don't even have access to that particular package with my current setup, and since I really don't (yet) need anything beyond the capitalizeFully method, I lose nothing by writing it myself. – Matt Ball Jul 21 '09 at 20:31
  • 9
    I respect your decision Matt, it's probably the right thing to do in your position. However, consider the following: * Someone else in your team decides they need a routine to swap the case of letters. They implement it. You now have ~20 lines to maintain. You would have ~2 if you used the library. And don't forget the unit tests! * The accepted answer has a downside in that the method name does not describe what the code does. A well reused API like the commons stuff rarely has those downsides. The point is that maintenance is the biggest cost of software. Generally, re-use is a good idea. – Dan Gravell Jul 22 '09 at 09:12
  • 2
    To "access this particular package", drop http://repo1.maven.org/maven2/commons-lang/commons-lang/2.5/commons-lang-2.5.jar into your classpath. The Maven artifact is **commons-lang:commons-lang:2.5** and it's readily available from Maven Central. – Hendy Irawan Dec 18 '10 at 07:25
96
static String toCamelCase(String s){
   String[] parts = s.split("_");
   String camelCaseString = "";
   for (String part : parts){
      camelCaseString = camelCaseString + toProperCase(part);
   }
   return camelCaseString;
}

static String toProperCase(String s) {
    return s.substring(0, 1).toUpperCase() +
               s.substring(1).toLowerCase();
}

Note: You need to add argument validation.

Alan Moore
  • 73,866
  • 12
  • 100
  • 156
C. Ross
  • 31,137
  • 42
  • 147
  • 238
  • 1
    Nice answer, but it would be a little better if either the method name described the fact that the string was split or that logic was externalised and the method calls aligned as a pipe, e.g. "THIS_IS_AN_EXAMPLE_STRING".removeUnderscores().toCamelCase() This is more reusable. – Dan Gravell Jul 22 '09 at 09:14
  • 1
    That's not necessarily *better* (though yes, it is more reusable). When it comes to name formatting conventions, camelcase can/does imply not using underscores; on the reverse side of the coin, there are conventions which specify using underscores. So in my mind, this is just a method to convert from one format to another. – Matt Ball Jul 24 '09 at 15:27
  • 63
    The Google guava library has a more general utility enum for converting between the common conventions. For this case you would do `String result = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, "THIS_IS_AN_EXAMPLE_STRING");`. See [com.google.common.base.CaseFormat javadoc](http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/base/CaseFormat.html). – George Hawkins Apr 26 '11 at 14:10
  • @GeorgeHawkins, you should have post it as an answer! – weekens May 08 '13 at 08:40
  • 1
    This answer will run into problems when used in locales like Turkish... If your code is going to be used in multiple locales, use toUpperCase(Locale) and toLowercase(Locale).. not the ones that depend on the default locale. – vkraemer May 15 '13 at 17:36
  • 2
    @DanGravell : once you remove the underscores, it is no longer possible to distinguish the words. – njzk2 Oct 09 '13 at 09:21
  • 1
    Just a note, toProperCase doesn't check for the length of `s`. If you change the separator from '_' to '' (split words by whitespace) it will fail if there is a space at the end of the string. As C.Ross said, I needed to add argument validation :P – orique Oct 25 '13 at 12:58
  • Nice answer without using any library – Shridutt Kothari Feb 24 '17 at 10:53
  • The accepted answer worked for me, until it converted `_rest_settings_clientId_clients` to `RestSettingsClientidClients` (note the i in id). I could easily update the method from answer to suit my needs. Thank you so much. – AJC Jan 04 '19 at 17:00
23

With Apache Commons Lang3 lib is it very easy.

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.text.WordUtils;

public String getName(String text) {
  return StringUtils.remove(WordUtils.capitalizeFully(text, '_'), "_");
}

Example:

getName("SOME_CONSTANT");

Gives:

"SomeConstant"
luckyluke
  • 491
  • 7
  • 16
librucha
  • 635
  • 8
  • 13
  • 3
    In case of variable name, this is not valid because the name must start with lowercase. – Seby Jan 11 '16 at 08:28
11

Here is a code snippet which might help:

String input = "ABC_DEF";
StringBuilder sb = new StringBuilder();
for( String oneString : input.toLowerCase().split("_") )
{
    sb.append( oneString.substring(0,1).toUpperCase() );
    sb.append( oneString.substring(1) );
}

// sb now holds your desired String
sud007
  • 5,824
  • 4
  • 56
  • 63
Alex B
  • 24,678
  • 14
  • 64
  • 87
  • This solution is appropriate for ALL_UPPER to Camel case. But a slight change in the program can also handle MixED_case or lower_case (snake case). I have suggested an edit if allowed. – sud007 Aug 16 '19 at 06:39
10

Java 1.8 example using 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 is now %s%n", text, dromedaryCamel); 

THIS_IS_SOME_TEXT is now thisIsSomeText

Mike
  • 1,390
  • 1
  • 12
  • 17
  • I like this answer, but it has a flaw if the input string is already in camel case, in which case it lower cases the entire input. e.g. abcDef becomes abcdef. – mrswadge Jun 27 '17 at 14:48
  • A test using `text.matches( "([a-z]+[a-zA-Z0-9]+)+" )` before camel casing is probably a reasonable workaround for the lower-casing issue. – mrswadge Jun 27 '17 at 15:05
  • Adding a filter before map would be useful to filer out empty String and avoid null pointer. `Stream.of(text.split("[^a-zA-Z0-9]")).filter(x -> x.length() > 0).map(v -> v.substring(0, 1).toUpperCase() + v.substring(1).toLowerCase()) .collect(Collectors.joining());` – sashwat Jun 21 '21 at 04:27
9
public static void main(String[] args) {
    String start = "THIS_IS_A_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);
}
Yishai
  • 90,445
  • 31
  • 189
  • 263
6

The Apache Commons project does now have the CaseUtils class, which has a toCamelCase method that does exactly as OP asked:

 CaseUtils.toCamelCase("THIS_IS_AN_EXAMPLE_STRING", true, '_');
Jacob van Lingen
  • 8,989
  • 7
  • 48
  • 78
3

Sorry for mine five cents, I think in java too many words)) I just wondering. Why is the regexp engine in java not so familiar with lambdas as in JS((

Anyway. With java 8+ construction appears in my mind:

Arrays.stream("THIS_IS_AN_EXAMPLE_STRING".split("_"))
    .collect(StringBuilder::new,
        (result, w) -> result
            .append(w.substring(0, 1).toUpperCase())
            .append(w.substring(1).toLowerCase()),
        StringBuilder::append)
    .toString())

If you care about memory consumption, the below code care about it:

"THIS_IS_AN_EXAMPLE_STRING".chars().collect(StringBuilder::new,
    (result, c) -> {
        // Detect place for deal with
        if (result.length() > 0 && result.charAt(result.length() - 1) == '_') {
            result.setCharAt(result.length() - 1,
                    Character.toUpperCase((char) c));
        } else if (result.length() > 0) {
            result.append(Character.toLowerCase((char) c));
        } else {
            result.append(Character.toUpperCase((char) c));
        }
    }, StringBuilder::append).toString()
Vanya Usalko
  • 405
  • 7
  • 10
  • That final StringBuilder::append needs to be replaced with a lambda that mirrors the provided logic, but by combining an entire StringBuilder with the "first" builder rather than just a single char. And SO won't let me revert my upvote. – SensorSmith Jan 31 '23 at 23:35
2

Not sure, but I think I can use less memory and get dependable performance by doing it char-by-char. I was doing something similar, but in loops in background threads, so I am trying this for now. I've had some experience with String.split being more expensive then expected. And I am working on Android and expect GC hiccups to be more of an issue then cpu use.

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

A hint that String.split is expensive is that its input is a regex (not a char like String.indexOf) and it returns an array (instead of say an iterator because the loop only uses one things at a time). Plus cases like "AB_AB_AB_AB_AB_AB..." break the efficiency of any bulk copy, and for long strings use an order of magnitude more memory then the input string.

Whereas looping through chars has no canonical case. So to me the overhead of an unneeded regex and array seems generally less preferable (then giving up possible bulk copy efficiency). Interested to hear opinions / corrections, thanks.

leorleor
  • 554
  • 5
  • 14
2
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<input.length(); ++i) {
        value = input.charAt(i);
        if (value == delim) {
            capitalize = true;
        }
        else if (capitalize) {
            sb.append(Character.toUpperCase(value));
            capitalize = false;
        }
        else {
            sb.append(value);
        }
    }

    return sb.toString();
}

public String withRegex(String inputa) {
    String input = inputa.toLowerCase();
    String[] parts = input.split("_");
    StringBuilder sb = new StringBuilder();
    sb.append(parts[0]);
    for (int i=1; i<parts.length; ++i) {
        sb.append(parts[i].substring(0,1).toUpperCase());
        sb.append(parts[i].substring(1));
    }

    return sb.toString();
}

Times: in milli seconds.

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

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

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

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

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

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

Iterations = 1000000000
WithChars: start = 1379685267523 end = 1379685397604 diff = 130081
WithRegex: start = 1379685397605 end = 1379685850582 diff = 452977
Srisa
  • 967
  • 1
  • 7
  • 17
  • Cool, is that iterating with input "THIS_IS_AN_EXAMPLE_STRING"? – leorleor Dec 20 '13 at 03:47
  • @leorleor Iteration = 1000000000 WithChars: start = 1387547394726 end = 1387547889896 diff = 495170 WithRegex: start = 1387547889897 end = 1387548944739 diff = 1054842 – Srisa Dec 20 '13 at 14:47
2

You can use org.modeshape.common.text.Inflector.

Specifically:

String camelCase(String lowerCaseAndUnderscoredWord,
    boolean uppercaseFirstLetter, char... delimiterChars) 

By default, this method converts strings to UpperCamelCase.

Maven artifact is: org.modeshape:modeshape-common:2.3.0.Final

on JBoss repository: https://repository.jboss.org/nexus/content/repositories/releases

Here's the JAR file: https://repository.jboss.org/nexus/content/repositories/releases/org/modeshape/modeshape-common/2.3.0.Final/modeshape-common-2.3.0.Final.jar

Hendy Irawan
  • 20,498
  • 11
  • 103
  • 114
1

You can Try this also :

 public static String convertToNameCase(String s)
    {
        if (s != null)
        {
            StringBuilder b = new StringBuilder();
            String[] split = s.split(" ");
            for (String srt : split)
            {
                if (srt.length() > 0)
                {
                    b.append(srt.substring(0, 1).toUpperCase()).append(srt.substring(1).toLowerCase()).append(" ");
                }
            }
            return b.toString().trim();
        }
        return s;
    }
Ashish
  • 11
  • 1
1
protected String toCamelCase(String input) {
    if (input == null) {
        return null;
    }

    if (input.length() == 0) {
        return "";
    }

    // lowercase the first character
    String camelCaseStr = input.substring(0, 1).toLowerCase();

    if (input.length() > 1) {
        boolean isStartOfWord = false;

        for (int i = 1; i < input.length(); i++) {
            char currChar = input.charAt(i);
            if (currChar == '_') {
                // new word. ignore underscore
                isStartOfWord = true;
            } else if (Character.isUpperCase(currChar)) {
                // capital letter. if start of word, keep it
                if (isStartOfWord) {
                    camelCaseStr += currChar;
                } else {
                    camelCaseStr += Character.toLowerCase(currChar);
                }
                isStartOfWord = false;
            } else {
                camelCaseStr += currChar;
                isStartOfWord = false;
            }
        }
    }

    return camelCaseStr;
}
Muzikant
  • 8,070
  • 5
  • 54
  • 88
1
public String CamelCase(String str)
{
    String CamelCase="";
    String parts[] = str.split("_");
    for(String part:parts)
    {
        String as=part.toLowerCase();
        int a=as.length();
        CamelCase = CamelCase + as.substring(0, 1).toUpperCase()+ as.substring(1,a);    
    }
    return CamelCase;
}

This is the Simplest Program to convert into CamelCase. hope it Will Help You..

XORG_99
  • 180
  • 4
  • 15
1
public static String toCamelCase(String value) {
    value = value.replace("_", " ");
    String[] parts = value.split(" ");
    int i = 0;
    String camelCaseString = "";
    for (String part : parts) {
        if (part != null && !part.isEmpty()) {
            if (i == 0) {
                camelCaseString = part.toLowerCase();
            } else if (i > 0 && part.length() > 1) {
                String oldFirstChar = part.substring(0, 1);
                camelCaseString = camelCaseString + part.replaceFirst(oldFirstChar, oldFirstChar.toUpperCase());
            } else {
                camelCaseString = camelCaseString + part + " ";
            }
            i++;
        }
    }
    return camelCaseString;
}

public static void main(String[] args) {
    String string = "HI_tHiS_is_SomE Statement";
    System.out.println(toCamelCase(string));
}
RoWi
  • 69
  • 5
0

It will convert Enum Constant into Camel Case. It would be helpful for anyone who is looking for such funtionality.

public enum TRANSLATE_LANGUAGES {
        ARABIC("ar"), BULGARIAN("bg"), CATALAN("ca"), CHINESE_SIMPLIFIED("zh-CN"), CHINESE_TRADITIONAL("zh-TW"), CZECH("cs"), DANISH("da"), DUTCH("nl"), ENGLISH("en"), ESTONIAN("et"), FINNISH("fi"), FRENCH(
                "fr"), GERMAN("de"), GREEK("el"), HAITIAN_CREOLE("ht"), HEBREW("he"), HINDI("hi"), HMONG_DAW("mww"), HUNGARIAN("hu"), INDONESIAN("id"), ITALIAN("it"), JAPANESE("ja"), KOREAN("ko"), LATVIAN(
                "lv"), LITHUANIAN("lt"), MALAY("ms"), NORWEGIAN("no"), PERSIAN("fa"), POLISH("pl"), PORTUGUESE("pt"), ROMANIAN("ro"), RUSSIAN("ru"), SLOVAK("sk"), SLOVENIAN("sl"), SPANISH("es"), SWEDISH(
                "sv"), THAI("th"), TURKISH("tr"), UKRAINIAN("uk"), URDU("ur"), VIETNAMESE("vi");

        private String code;

        TRANSLATE_LANGUAGES(String language) {
            this.code = language;
        }

        public String langCode() {
            return this.code;
        }

        public String toCamelCase(TRANSLATE_LANGUAGES lang) {
            String toString = lang.toString();
            if (toString.contains("_")) {
                String st = toUpperLowerCase(toString.split("_"));
            }

            return "";
        }

        private String toUpperLowerCase(String[] tempString) {
            StringBuilder builder = new StringBuilder();

            for (String temp : tempString) {

                String char1 = temp.substring(0, 1);
                String restString = temp.substring(1, temp.length()).toLowerCase();
                builder.append(char1).append(restString).append(" ");

            }

            return builder.toString();
        }
    }
AZ_
  • 21,688
  • 25
  • 143
  • 191
0

One more solution to this may be as follows.

public static String toCamelCase(String str, String... separators) {
    String separatorsRegex = "\\".concat(org.apache.commons.lang3.StringUtils.join(separators, "|\\"));
    List splits = Arrays.asList(str.toLowerCase().split(separatorsRegex));
    String capitalizedString = (String)splits.stream().map(WordUtils::capitalize).reduce("", String::concat);
    return capitalizedString.substring(0, 1).toLowerCase() + capitalizedString.substring(1);
}
Sajani
  • 117
  • 8
0
public static final String  UPPER_CAMEL = "initUp";
public static final String  LOWER_CAMEL = "initLow";

public String toCamel(String src, String separator, String format) {
    StringBuilder builder = new StringBuilder(src.toLowerCase());
    int len = builder.length();

    for (int idx = builder.indexOf(separator); idx > 0 && idx < len; idx = builder.indexOf(separator, idx)) {
        builder = builder.replace(idx, idx + 2, (String.valueOf(builder.charAt(idx + 1)).toUpperCase()));
    }

    switch (format) {
    case LOWER_CAMEL:
        builder.setCharAt(0, Character.toLowerCase(builder.charAt(0)));
        break;
    default:
        builder.setCharAt(0, Character.toUpperCase(builder.charAt(0)));
        break;
    }

    return builder.toString();

}

Invocation as

toCamel("THIS_IS_AN_EXAMPLE_STRING", "_", UPPER_CAMEL)

Execution Time: 14 ms

Arindam
  • 24
  • 3
0

A simple snnipet:

 public static String camelCase(String in) {
    if (in == null || in.length() < 1) { return ""; } //validate in
    String out = "";
    for (String part : in.toLowerCase().split("_")) {
        if (part.length() < 1) { //validate length
            continue;
        }
        out += part.substring(0, 1).toUpperCase();
        if (part.length() > 1) { //validate length
            out += part.substring(1);
        }
    }
    return out;
}
fitorec
  • 4,257
  • 2
  • 24
  • 18
-3
    protected String toCamelCase(CaseFormat caseFormat, String... words){
        if (words.length  == 0){
          throw new IllegalArgumentException("Word list is empty!");
        }

        String firstWord = words[0];
        String [] restOfWords = Arrays.copyOfRange(words, 1, words.length);

        StringBuffer buffer = new StringBuffer();
        buffer.append(firstWord);
        Arrays.asList(restOfWords).stream().forEach(w->buffer.append("_"+ w.toUpperCase()));

        return CaseFormat.UPPER_UNDERSCORE.to(caseFormat, buffer.toString());

    }
Vladimir
  • 1,120
  • 2
  • 11
  • 18
-4

Java 8 for multiple strings:

import com.google.common.base.CaseFormat;



String camelStrings = "YOUR_UPPER, YOUR_TURN, ALT_TAB";

List<String> camelList = Arrays.asList(camelStrings.split(","));
camelList.stream().forEach(i -> System.out.println(CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, i) + ", "));
DET66
  • 183
  • 2
  • 2
  • 8