9
\$\begingroup\$

I have a requirement to put a comma between each digit of a number in a Java string.

Example input:

the number is 12345 and the number is 45678

The output should be:

the number is 1,2,3,4,5 and the number is 4,5,6,7,8

I wrote the following and I am not sure if it is optimized. If someone reviews it and help me fine tune it, it will be helpful.

public static void main(String args[]) {
      String str = "the number is 12345 and the number is 45678";
      System.out.println("Original Text:\n" + str);
      System.out.println("Updated Text:\n" + formatNumber(str, ','));
   }

   public static String formatNumber(String text, char separator) {
       Pattern p = Pattern.compile("\\d+");
       Matcher m = p.matcher(text);
       StringBuffer sb = new StringBuffer();
       while(m.find()) {
           String num = m.group();
           num = num.replaceAll(".(?!$)", "$0"+separator);
           m.appendReplacement(sb,num);
       }
       return m.appendTail(sb).toString();
   }

Output:

Original Text:
    the number is 12345 and the number is 45678
    Updated Text:
    the number is 1,2,3,4,5 and the number is 4,5,6,7,8
    Process finished with exit code 0

Though it gave me the output I wanted, I have a feeling that it is not highly optimized when the string size grows larger and larger.

\$\endgroup\$
7
\$\begingroup\$

Two of the really nice things about regular expressions are:

  1. they can be compiled, which makes them fast, and reusable
  2. they can replace what's between characters, not just the characters themselves.

In your case, you can reduce it to a "simple" lookaround regular expression. What you are looking for, is the gap between two digits...

in a regular expression, the gap can have no width. So, look for a place that follows a digit, and is also followed by a digit. Then, replace that place with a separator.

Then, compile and save that expression away, and reuse it:

private static final Pattern BETWEEN_DIGITS = Pattern.compile("(?<=\\d)(?=\\d)");

public static String formatNumber(String text, char separator) {
    return BETWEEN_DIGITS.matcher(text).replaceAll("" + separator);
}

That pattern is complicated.... but read up on look-behinds, and look-aheads: http://www.regular-expressions.info/lookaround.html

\$\endgroup\$
  • 5
    \$\begingroup\$ "" + separator, seriously? I used to do those ugly-tricks myself once. These days I always do String.valueOf or Character.toString. I don't think I need to tell you what goes on behind the scenes of "" + x (StringBuilder bla bla bla) \$\endgroup\$ – Simon Forsberg Oct 22 '15 at 20:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.