2

I have a String str = "a_bcde_fghij_k".

and I want to change it to "aBcdeFghijK"

If have a _ character, the next character will be change to uppercase and remove _ character.

How can I do this?

Vijay
  • 8,131
  • 11
  • 43
  • 69
furyfish
  • 2,055
  • 5
  • 26
  • 28

6 Answers6

10

I suspect you'll need to just go through this character by character, building up the string as you go. For example:

public static String underscoreToCapital(String text) {
    // This will be a bit bigger than necessary, but that shouldn't matter.
    StringBuilder builder = new StringBuilder(text.length());
    boolean capitalizeNext = false;
    for (int i = 0; i < text.length(); i++) {
        char c = text.charAt(i);
        if (c == '_') {
            capitalizeNext = true;
        } else {
            builder.append(capitalizeNext ? Character.toUpperCase(c) : c);
            capitalizeNext = false;
        }
    }
    return builder.toString();
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I think regexes give much simpler code, but probably a slower one. – m0skit0 Jul 16 '13 at 08:48
  • Oh btw it's `text.length()` ;) – m0skit0 Jul 16 '13 at 09:09
  • @m0skit0: Fixed, thanks. But I still prefer this over the regex version :) – Jon Skeet Jul 16 '13 at 09:28
  • @JonSkeet Ok I understand :) But I've learned a lesson: never waste my time again writing answers when you answer xD Have a nice day! :) – m0skit0 Jul 16 '13 at 09:48
  • @JonSkeet +10 upvotes and accepted... but this is not working. Did anyone try this? For input `a_acde_fghij_k` it returns `AaCDEfGHIJk`, which as I understood the question, is wrong. This `capitalizeNext ? c : Character.toUpperCase(c)` looks like swapped up. – m0skit0 Jul 16 '13 at 14:00
  • @m0skit0: No, you were right - I just had a typo. Fixed now, thanks. – Jon Skeet Jul 16 '13 at 14:02
  • If you change `if(c == '_')` to `if(c == '_' && !capitalizeNext)`, you gain implicit support for escaping. – Brian Jul 17 '13 at 17:05
  • @Brian: Given that that wasn't in the specification, I wouldn't want to do it at the moment... – Jon Skeet Jul 17 '13 at 18:23
4

Regular expressions alone can't do that (there is no "touppercase" operator, so to speak).

But Guava has a nice little utility called CaseFormat that can help you:

String result = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, str)

This works, even 'though your input is not strictly in UPPER_UNDERSCORE format, but CaseFormat is lenient this way (if you want the first character to be capitalized as well use UPPER_CAMEL instead).

Alternatively, if you absolutely want to use regular expressions, you can use Matcher.appendReplacement (it has a nice example in the JavaDoc):

public static final Pattern UNDERSCORE_FOLLOWED_BY_ANYTHING = Pattern
        .compile("_(.)");

public static String toUpperAfterUnderscore(String input) {
    Matcher m = UNDERSCORE_FOLLOWED_BY_ANYTHING.matcher(input);
    StringBuffer sb = new StringBuffer();
    while (m.find()) {
        m.appendReplacement(sb, m.group(1).toUpperCase());
    }
    m.appendTail(sb);
    return sb.toString();
}
Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
  • Nice answer, useful info but hmmm external libraries... +1 anyway – m0skit0 Jul 16 '13 at 09:01
  • 1
    @m0skit0: Guava contains so many useful little utilities, that it really ought to be a dependency of every non-trivial project (and quite a few trivial ones). – Joachim Sauer Jul 16 '13 at 09:02
2

You can also try splitting.

String str = "a_bcde_fghij_k"
String result[] = str.split("_");
String newstr = result[0];
for (int i=1;i<result.length;i++) {
     char first = Character.toUpperCase(result[i].charAt(0));
     newstr = newstr + first + result[i].substring(1);
}
System.out.println(newstr);

split() takes regex, if you feel that is important.

Mark M
  • 1,580
  • 10
  • 22
  • 1
    This also uses `String` for concatenation, it should really use `StringBuilder` (or at least `StringBuffer`), they are *made* to be manipulated. – Joachim Sauer Jul 16 '13 at 09:05
1

A slightly different approach from me but works good..

  String str = "a_bcde_fghij_k";
  int count=0;
  String[] splitString = (str.split("_"));

  for (String string : splitString)
  {
    count++;        
    if(count>1)
    {
        char c= string.charAt(0);
        System.out.print(string.replace(c, Character.toUpperCase(c)));
    }
    else
        System.out.print(string);
  }

Isn't it?

ridoy
  • 6,274
  • 2
  • 29
  • 60
0

There's no straight away way to do it with regexes, but I think using regexes can greatly simplify the task:

public static String underscoreToCapital(final String input) {
    String ret = input;
    final Matcher m = Pattern.compile("_([a-z])").matcher(input);
    while (m.find()) {
        final String found = m.group();
        final String toUppercase = m.group(1);
        ret = ret.replaceAll(found, toUppercase.toUpperCase());
    }
    return ret;
}
m0skit0
  • 25,268
  • 11
  • 79
  • 127
  • I don't think that's simpler, personally. (I retract my suggestion that it doesn't work, but I still don't think it's as clear as just iterating.) – Jon Skeet Jul 16 '13 at 08:56
  • Input: `a_acde_fghij_k` Ouput: `a_Acde_Fghij_K` Is this what you mean? Also edited it to match the question, I was keeping the underscore... – m0skit0 Jul 16 '13 at 08:57
  • @JonSkeet answer edit made your comment right :) Edited it again so now it does work correctly. – m0skit0 Jul 16 '13 at 09:00
  • @JonSkeet I do think it's more readable and maintainable than iterating over all the characters (probably because I'm used to working with regexes). Also shorter code means lesser bugs ;) And your comment about it not working was definitely right, thanks for correcting. – m0skit0 Jul 16 '13 at 09:04
0

You have to do probably some check on the execution of this method but this could be another idea:

public String replaceAndUpper(String word) {
    int charToRemove = word.indexOf("_");
    while (charToRemove != -1) {
        String part1 = word.substring(0, charToRemove);
        String part2 = word.substring(charToRemove + 1);
        char upperChar = Character.toUpperCase(part2.charAt(0));
        word = part1 + String.valueOf(upperChar) + part2.substring(1);
        charToRemove = word.indexOf("_");
    }
    return word;
}
Enrichman
  • 11,157
  • 11
  • 67
  • 101
  • 1
    You should use a StringBuilder/Buffer (for building the result) which are used for these kind of concatenations (provides better performance) – giorashc Jul 16 '13 at 09:01
  • Yep, that could be an improvement. Btw, the '+' should be internally converted to use a StringBuilder if I'm not wrong. – Enrichman Jul 16 '13 at 09:06
  • Also too much calls to substring. Using `String#charAt()` is way better. – m0skit0 Jul 16 '13 at 09:07
  • @Enrichman [You're wrong](http://stackoverflow.com/questions/2721998/how-java-do-the-string-concatenation-using). – m0skit0 Jul 16 '13 at 09:07
  • How do you split then? With charAt I can get the Character to remove/capitalize, but thenk I have to split and rebuild the String. – Enrichman Jul 16 '13 at 09:09
  • @m0skit0 actually they're saying that is, more or less, up to the compiler. Probably it won't use the most efficient way but it will probably use a StringBuilder. Btw, I guess it's not noticeble for a String like the one the op posted (at least in a small loop, of course). – Enrichman Jul 16 '13 at 09:14
  • Yes probably, but you can just StringBuffer/StringBuilder and forget about it ;) – m0skit0 Jul 16 '13 at 09:15