将Java字符串从所有大写字母(用下划线分隔的单词)转换为CamelCase(无单词分隔符)的最简单方法是什么?


151

标题基本概括了所有内容。我可以用Java将字符串从格式转换"THIS_IS_AN_EXAMPLE_STRING"为“ ThisIsAnExampleString” 的最简单/最优雅的方法是什么?我认为必须至少有一种使用String.replaceAll()正则表达式的方法。

我最初的想法是:在字符串前加一个下划线(_),将整个字符串转换为小写,然后使用replaceAll转换后跟下划线及其大写版本的每个字符。


12
编者按,2015-03年:上面的“初步想法”非常愚蠢。您将在六年内学到很多有关构建软件的知识。
马特·鲍尔

4
那一刻,当你问“白痴是怎么写的”,然后查看源代码控制来发现你那年轻,愚蠢的人。去过也做过。
pierus

@MattBall:我喜欢最初的想法版本,它不需要库,只需要一个字符串连接和两个正则表达式替换即可。
KonradHöffner19年

Answers:


192

另一个选择是使用Google Guava的 com.google.common.base.CaseFormat

乔治·霍金斯对此用法示例发表了评论:

CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, "THIS_IS_AN_EXAMPLE_STRING");

3
有关示例,请参见George Hawkins的评论[user:245602]。stackoverflow.com/questions/1143951/...
迈克尔Scheper

5
我在为Android开发时想念纯Java答案。
eliocs 2014年

1
这个答案对我来说最有用。我可以很好地编写自己的代码,但是如果其他人已经拥有了,我当然不想重新发明轮子。
James Dunn 2014年


1
@CléssioMendes您是否考虑过在github.com/google/guava/issues中提出此要求
Arnout Engelen '18

128

看看Apache Commons lang中的WordUtils库:

具体来说,capitalizeFully(String str,char [] delimiters)方法应该可以完成以下工作:

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

绿色吧!


55
不,先生!我们应该自己重写这些现有的,已经在使用的实用程序,因为我们是合适的程序员!
skaffman 2009年

24
星期五下午16:42。我让其他所有人重写它,我要去喝啤酒\ o /;)
Dan Gravell

1
更重要的是,在我当前的设置中,我什至无法访问该特定程序包,并且由于我真的(除)还不需要资本化方法之外的任何东西,因此我自己编写该程序不会造成任何损失。
马特·鲍尔

7
我尊重您的决定,马特(Matt),这可能是对您有利的选择。但是,请考虑以下因素:*团队中的其他人认为他们需要一个例程来交换大写字母。他们实现了它。现在,您需要维护约20行。如果您使用该库,则将有〜2。并且不要忘记单元测试!*可接受的答案有一个缺点,即方法名称未描述代码的作用。像Commons这样的可重用的API几乎没有这些缺点。关键是维护是软件的最大成本。通常,重用是个好主意。
丹·格雷弗

2
要“访问此特定程序包”,请将repo1.maven.org/maven2/commons-lang/commons-lang/2.5/…放入您的类路径中。Maven工件是commons-lang:commons-lang:2.5,可以从Maven Central轻松获得。
Hendy Irawan 2010年

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

注意:您需要添加参数验证。


1
好的答案,但是如果方法名称描述了字符串已拆分或逻辑被外部化并且方法调用作为管道对齐的事实会更好一些,例如“ THIS_IS_AN_EXAMPLE_STRING”。removeUnderscores()。toCamelCase()更可重用。
丹·格雷弗尔

1
这不一定更好(尽管是的,它更可重用)。当涉及到名称格式约定时,camelcase可以/确实暗示不使用下划线。在硬币的背面,有使用下划线指定的约定。因此,在我看来,这只是一种从一种格式转换为另一种格式的方法。
Matt Ball

58
Google guava库具有一个更通用的实用程序枚举,可用于在通用约定之间进行转换。对于这种情况,您可以这样做String result = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, "THIS_IS_AN_EXAMPLE_STRING");。请参阅com.google.common.base.CaseFormat javadoc
乔治·霍金斯

1
在土耳其语等语言环境中使用时,此答案会出现问题。如果您的代码要在多个语言环境中使用,请使用toUpperCase(Locale)和toLowercase(Locale)..而不是依赖于默认语言环境的代码。
vkraemer

2
@DanGravell:删除下划线后,就不再可能区分单词。
njzk2

18

使用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"

2
对于变量名,这是无效的,因为名称必须以小写字母开头。
Seby

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

3
不需要进行s.length测试
13年

9

以下代码片段可能会有所帮助:

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

此解决方案适用于ALL_UPPER至Camel的情况。但是在程序中稍作更改也可以处理MixED_case或lower_case(蛇案)。我建议编辑(如果允许)。
sud007

6

使用Streams的Java 1.8示例

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


我喜欢这个答案,但是如果输入字符串已经是驼峰式的话,那是有缺陷的,在这种情况下,它会小写整个输入。例如,abcDef变为abcdef。
mrswadge

使用text.matches( "([a-z]+[a-zA-Z0-9]+)+" )骆驼前套管进行测试可能是解决下套管问题的合理解决方法。
mrswadge

2

不能确定,但​​是我认为通过逐个字符地进行处理,我可以使用更少的内存并获得可靠的性能。我在做类似的事情,但是在后台线程中处于循环中,所以我现在尝试这样做。我有一些String.split的经验,它比预期的要贵。我正在Android上工作,希望GC打ic比使用CPU更为重要。

  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 ...”之类的示例,将破坏任何批量复制的效率,并且对于长字符串,使用的内存要比输入字符串多一个数量级。

循环遍历字符没有规范的情况。因此,对我而言,不需要的正则表达式和数组的开销通常似乎不太理想(然后放弃了可能的批量复制效率)。有兴趣听取意见/更正,谢谢。


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

时间:以毫秒为单位。

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

太酷了,是使用输入“ THIS_IS_AN_EXAMPLE_STRING”进行迭代吗?
leorleor

@leorleor迭代= 1000000000 WithChars:开始= 1387547394726结束= 1387547889896 diff = 495170 WithRegex:开始= 1387547889897结束= 1387548944739 diff = 1054842
Srisa 2013年

1

您可以使用org.modeshape.common.text.Inflector

特别:

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

默认情况下,此方法将字符串转换为UpperCamelCase。

Maven工件是:org.modeshape:modeshape-common:2.3.0.Final

在JBoss存储库上: https //repository.jboss.org/nexus/content/repositories/releases

这是JAR文件:https : //repository.jboss.org/nexus/content/repositories/releases/org/modeshape/modeshape-common/2.3.0.Final/modeshape-common-2.3.0.Final.jar


1

您也可以尝试以下方法:

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

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

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

这是转换为CamelCase的最简单程序。希望对您有帮助。


0

它将转换Enum Constant成骆驼套。这将对正在寻求这种功能性的任何人有所帮助。

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

0

对此的另一解决方案如下。

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

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

}

调用为

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

执行时间:14 ms


0

一个简单的片段:

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

-2

Java 8用于多个字符串:

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) + ", "));

1
重复的答案
Mark Jeronimus

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

    }

1
CaseFormat不是标准的API。如果是番石榴,请重复回答。
Mark Jeronimus
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.