如何在Java中将CamelCase转换为人类可读的名称?

Fre*_*rik 149 java regex string camelcasing humanize

我想编写一个将CamelCase转换为人类可读名称的方法.

这是测试用例:

public void testSplitCamelCase() {
    assertEquals("lowercase", splitCamelCase("lowercase"));
    assertEquals("Class", splitCamelCase("Class"));
    assertEquals("My Class", splitCamelCase("MyClass"));
    assertEquals("HTML", splitCamelCase("HTML"));
    assertEquals("PDF Loader", splitCamelCase("PDFLoader"));
    assertEquals("A String", splitCamelCase("AString"));
    assertEquals("Simple XML Parser", splitCamelCase("SimpleXMLParser"));
    assertEquals("GL 11 Version", splitCamelCase("GL11Version"));
}
Run Code Online (Sandbox Code Playgroud)

pol*_*nts 322

这适用于您的测试用例:

static String splitCamelCase(String s) {
   return s.replaceAll(
      String.format("%s|%s|%s",
         "(?<=[A-Z])(?=[A-Z][a-z])",
         "(?<=[^A-Z])(?=[A-Z])",
         "(?<=[A-Za-z])(?=[^A-Za-z])"
      ),
      " "
   );
}
Run Code Online (Sandbox Code Playgroud)

这是一个测试工具:

    String[] tests = {
        "lowercase",        // [lowercase]
        "Class",            // [Class]
        "MyClass",          // [My Class]
        "HTML",             // [HTML]
        "PDFLoader",        // [PDF Loader]
        "AString",          // [A String]
        "SimpleXMLParser",  // [Simple XML Parser]
        "GL11Version",      // [GL 11 Version]
        "99Bottles",        // [99 Bottles]
        "May5",             // [May 5]
        "BFG9000",          // [BFG 9000]
    };
    for (String test : tests) {
        System.out.println("[" + splitCamelCase(test) + "]");
    }
Run Code Online (Sandbox Code Playgroud)

它使用零长度匹配正则表达式与lookbehind和lookforward来查找插入空格的位置.基本上有3种模式,我用String.format它们将它们放在一起以使其更具可读性.

这三种模式是:

UC在我身后,UC跟在我面前的LC

  XMLParser   AString    PDFLoader
    /\        /\           /\
Run Code Online (Sandbox Code Playgroud)

非UC在我身后,UC在我面前

 MyClass   99Bottles
  /\        /\
Run Code Online (Sandbox Code Playgroud)

在我身后的信,在我面前的非信

 GL11    May5    BFG9000
  /\       /\      /\
Run Code Online (Sandbox Code Playgroud)

参考

相关问题

使用零长度匹配的外观来分割:

  • 有人可以解释一下%s |%s |%s对于测试用例的意义吗? (2认同)

Ral*_*lph 110

你可以用它来做 org.apache.commons.lang.StringUtils

StringUtils.join(
     StringUtils.splitByCharacterTypeCamelCase("ExampleTest"),
     ' '
);
Run Code Online (Sandbox Code Playgroud)

  • 这个解决方案比最受欢迎的解决方案要好得多,因为:a)它没有重新发明轮子:commons-lang是事实上的标准,它工作正常,非常注重性能.b)转换完成很多次后,这个方法比基于正则表达式的方法要快得多:这是我执行上述测试100,000次的基准:`````regex-based method花了4820毫秒///// /////基于commons-lang的方法花了232毫秒```这比使用正则表达式的方法快20倍! (9认同)
  • 我绝对同意克林特的观点,这应该是公认的答案.性能是一件事,但使用经过实战考验的库肯定是一个很好的编程实践. (2认同)

Sah*_*bra 15

整洁而简短的解决方案:

StringUtils.capitalize(StringUtils.join(StringUtils.splitByCharacterTypeCamelCase("yourCamelCaseText"), StringUtils.SPACE)); // Your Camel Case Text
Run Code Online (Sandbox Code Playgroud)


jlb*_*b83 9

如果你不喜欢"复杂的"正则表达式,并且完全不关心效率,那么我已经用这个例子在三个阶段达到了同样的效果.

String name = 
    camelName.replaceAll("([A-Z][a-z]+)", " $1") // Words beginning with UC
             .replaceAll("([A-Z][A-Z]+)", " $1") // "Words" of only UC
             .replaceAll("([^A-Za-z ]+)", " $1") // "Words" of non-letters
             .trim();
Run Code Online (Sandbox Code Playgroud)

它通过了上面的所有测试用例,包括带有数字的测试用例.

正如我所说,这不如在这里的其他一些例子中使用一个正则表达式那么好 - 但有人可能会发现它很有用.


Hen*_*wan 6

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

特别:

String humanize(String lowerCaseAndUnderscoredWords,
    String... removableTokens) 
Run Code Online (Sandbox Code Playgroud)

将第一个单词大写并将下划线转换为空格并剥离尾随"_id"和任何提供的可移动标记.

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