Как проще всего преобразовать строку Java из всех заглавных букв (слова, разделенные подчеркиванием) в CamelCase (без разделителей слов)? - PullRequest
132 голосов
/ 17 июля 2009

Название в значительной степени говорит само за себя. Какой самый простой / самый элегантный способ, которым я могу преобразовать в Java строку из формата "THIS_IS_AN_EXAMPLE_STRING" в формат "ThisIsAnExampleString"? Я полагаю, что должен быть хотя бы один способ сделать это, используя String.replaceAll() и регулярное выражение.

Мои первоначальные мысли таковы: добавьте строку с нижним подчеркиванием (_), преобразуйте всю строку в нижний регистр, а затем используйте replaceAll, чтобы преобразовать каждый символ, которому предшествует подчеркивание, в версию из верхнего регистра.

Ответы [ 19 ]

166 голосов
/ 21 мая 2013

Другой вариант - использование Google Guava's com.google.common.base.CaseFormat

Джордж Хокинс оставил комментарий с этим примером использования:

CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, "THIS_IS_AN_EXAMPLE_STRING");
114 голосов
/ 17 июля 2009

Взгляните на WordUtils в библиотеке Apache Commons lang :

В частности, метод capitalizeFully (String str, char [] delimiters) должен выполнять эту работу:

String blah = "LORD_OF_THE_RINGS";
assertEquals("LordOfTheRings", WordUtils.capitalizeFully(blah, new char[]{'_'}).replaceAll("_", ""));

Зеленая полоса!

82 голосов
/ 17 июля 2009
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();
}

Примечание : необходимо добавить проверку аргумента.

16 голосов
/ 20 августа 2014

С Apache Commons Lang3 lib это очень просто.

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

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

Пример:

getName("SOME_CONSTANT");

Дает:

"SomeConstant"
9 голосов
/ 17 июля 2009
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);
}
5 голосов
/ 17 июля 2009

Вот фрагмент кода, который может помочь:

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

// sb now holds your desired String
4 голосов
/ 24 мая 2016

Пример Java 1.8 с использованием 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 теперь thisIsSomeText

2 голосов
/ 20 сентября 2013
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();
}

Время: в миллисекундах.

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
2 голосов
/ 11 января 2013

Не уверен, но я думаю, что смогу использовать меньше памяти и получить надежную производительность, выполняя ее char-by-char. Я делал что-то подобное, но в циклах в фоновых потоках, поэтому я пытаюсь это сейчас. У меня был некоторый опыт работы с String.split, который оказался дороже, чем ожидалось. И я работаю над Android и ожидаю, что сбой GC станет более серьезной проблемой, чем использование процессора.

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

Намек на то, что String.split дорогой, заключается в том, что его входные данные являются регулярным выражением (а не символом, подобным String.indexOf) и возвращают массив (вместо, скажем, итератора, поскольку цикл использует только одну вещь за раз). Плюс такие случаи, как "AB_AB_AB_AB_AB_AB ...", снижают эффективность любой объемной копии, а для длинных строк используют на порядок больше памяти, чем входная строка.

Принимая во внимание, что цикл через символы не имеет канонического случая. Поэтому мне кажется, что издержки из-за ненужных регулярных выражений и массива, как правило, менее предпочтительны (чем отказ от возможной эффективности массового копирования). Заинтересованы услышать мнения / исправления, спасибо.

1 голос
/ 27 июня 2014

Вы можете попробовать это также:

 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;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...