javaregexstringpascalcasinghumanize

How do I convert CamelCase into human-readable names in Java?


I'd like to write a method that converts CamelCase into a human-readable name.

Here's the test case:

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

Solution

  • This works with your testcases:

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

    Here's a test harness:

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

    It uses zero-length matching regex with lookbehind and lookforward to find where to insert spaces. Basically there are 3 patterns, and I use String.format to put them together to make it more readable.

    The three patterns are:

    UC behind me, UC followed by LC in front of me

      XMLParser   AString    PDFLoader
        /\        /\           /\
    

    non-UC behind me, UC in front of me

     MyClass   99Bottles
      /\        /\
    

    Letter behind me, non-letter in front of me

     GL11    May5    BFG9000
      /\       /\      /\
    

    References

    Related questions

    Using zero-length matching lookarounds to split: