7
\$\begingroup\$

I'm working with an API which gives me 19-digit ID numbers, formatted in blocks of four except for the last 3 digits. While I tried a for loop, I thought it would be most efficient to simply use a StringBuilder and substrings as the length of the ID will never change (documentation is omitted for privacy reasons):

public String getFormattedId() {
    return new StringBuilder()
            .append(id.substring(0, 4))
            .append(" ")
            .append(id.substring(4, 8))
            .append(" ")
            .append(id.substring(8, 12))
            .append(" ")
            .append(id.substring(12, 16))
            .append(" ")
            .append(id.substring(16, 19))
            .toString();
}

This transforms IDs like 1234567890000000123 into the more readable 1234 5678 9000 0000 123, which is also the format used throughout the documentation and website.

I should mention I come from a C# background, and I've heard Java's string + operator is just syntactic sugar for the StringBuilder method like I'm using here.

\$\endgroup\$
  • \$\begingroup\$ Your method seems to be missing its id parameter. I'm also not seeing an actual question here. Is it not efficient enough? Do you just want general style/clarity feedback? \$\endgroup\$ – Chris Hayes Mar 14 '15 at 9:26
  • \$\begingroup\$ @ChrisHayes The id can be a field of the class. \$\endgroup\$ – Simon Forsberg Mar 14 '15 at 9:29
  • 1
    \$\begingroup\$ @Simon Good point. Worth mentioning in the question if it is, since it changes the available optimizations if the asker is super concerned about performance. \$\endgroup\$ – Chris Hayes Mar 14 '15 at 9:31
  • \$\begingroup\$ Forgot to mention that id is a field in a model class. \$\endgroup\$ – svbnet Mar 14 '15 at 9:59
  • 1
    \$\begingroup\$ a little advice: when you need to use a single space symbol, it is better to code it like a char symbol: ' ' (not a string as " ") \$\endgroup\$ – Vladimir Kishlaly Mar 14 '15 at 12:21
4
\$\begingroup\$

It is things like this which drive me nuts, and I agree with you, your solution is good, but ugly. Your solution is also probably close to being as efficient as possible in Java, using the StringBuilder, etc.

There are a couple of things through that you can do to xhange the way you code it. Note that your solution may well be the fastest.... (well, it would be the fastest if you specified a starteing capactity of 23 for the StringBuilder like new StringBuilder(23) ...

How about a for-loop:

private static String formatID(String id) {
    StringBuilder sb = new StringBuilder(25);
    for (int i = 0; i < id.length(); i += 4) {
        sb.append(id.substring(i, Math.min(i + 4, id.length())));
        sb.append(" ");
    }
    sb.setLength(23);
    return sb.toString();
}

The last setLength(23) removes the trailing space on the output.

The actual suggestion I prefer, though, is using a format String, like:

private static String formatFID(String id) {
    return String.format("%s %s %s %s %s", id.substring(0, 4), id.substring(4,  8),
            id.substring(8,  12), id.substring(12,  16), id.substring(16, 19));
}

Finally, for completeness, you can actually use a regex to split the input string at 4-char boundaries. Then, in Java 8, stream the results, and join them with a space:

private static final Pattern FOUR = Pattern.compile("(?<=\\G.{4})");

private static String formatRID(String id) {
    return Stream.of(FOUR.split(id)).collect(Collectors.joining(" "));
}

That's a concise way of doing it.....

\$\endgroup\$
  • \$\begingroup\$ The format string method looks really good. However I can't use Java 8 because I'm working on an Android app. \$\endgroup\$ – svbnet Mar 16 '15 at 5:39

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.