4
\$\begingroup\$

I have written a custom method to use StringBuilder in java. My Requirement is to create a method which accepts any number of arguments of any type and return String by concatenating the arguments.

eg. msgBuilder("Hello ",0," how"," are"," you ",2.5) return "Hello 0 how are you 2.5"

Here is my java code. Please Someone review my code and suggest If I did anything is wrong or Can I use this further in my projects.

        public class Test {
            public static void main(String[] args ){
                String msg = msgBuilder("Hello ",5," How ","are ","you");
                System.out.println(msg);
            }

            private static String msgBuilder(Object... params){
                StringBuilder sb = new StringBuilder();
                for(Object obj:params){
                    sb.append(obj);
                }
                return sb.toString();
            }
        }
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Any particular reason why you are reinventing-the-wheel? \$\endgroup\$ Commented May 27, 2016 at 12:39
  • \$\begingroup\$ Some logging frameworks allow parameterized String formatting, have you checked if your logging framework of choice has it? Also, are you on Java 8? \$\endgroup\$ Commented May 27, 2016 at 15:22
  • \$\begingroup\$ Yes I am using java 8 and using apache4j Logger \$\endgroup\$ Commented May 27, 2016 at 15:30

4 Answers 4

1
\$\begingroup\$

I had this in mind:

private static String msgBuilder(Object... params) {
    StringBuilder sb = new StringBuilder();

    if (params.length > 0) {
        sb.append(params[0]);
    }

    for (int i = 1; i < params.length; ++i) {
        sb.append(" ").append(params[i]);
    }

    return sb.toString();
}

The above version allows you not to hardcode the white space delimiting your tokens. Instead of saying

String msg = msgBuilder("Hello ", 5, " How ", "are ", "you");

you can say succintly

String msg = msgBuilder("Hello", 5, "How", "are", "you");

Hope that helps.

\$\endgroup\$
5
\$\begingroup\$

Your approach

As pointed out by the other answers, you are practically hard-coding whitespaces in your arguments, which can get non-standard easily, even in your example. Otherwise, the use of StringBuilder is sound, although it wouldn't deal nicely with a single null value - the for-each loop will fail as it implicitly tries to get an Iterator for it.

Java 8

An alternative is to rely on the stream-based processing that Java 8 offers:

private static String format(Object... values) {
    if (values == null) {
        return "";
    }
    return Arrays.stream(values)
                    .map(Objects::toString)
                    .collect(Collectors.joining(" "));
}
  1. Construct a Stream<Object> from values using Arrays.stream(T...).
  2. map() each value using Objects.toString(Object) as a method reference.
  3. collect() the stream into a String by joining(" ") them together.
\$\endgroup\$
2
  • \$\begingroup\$ Will it be as efficient as StringBuilder() \$\endgroup\$ Commented May 29, 2016 at 6:39
  • \$\begingroup\$ Yes, it uses the new StringJoiner class as the underlying implementation, which in turn uses a StringBuilder. \$\endgroup\$ Commented May 29, 2016 at 7:22
2
\$\begingroup\$

I just decompiled the below code in java version "1.8.0_73" and found that compiler is automatically optimizing the code for strings

            String hello = "a" + "b" + "c" + " hello " + " world ";
            System.out.println("Hello World!!");

            String a="a";
            String b="b";
            String c="c";
            String d=a+b+c;
            System.out.println(d);  
            System.out.println(a +" yo "+ b); 

Code after decompiling

            String s = "abc hello  world ";
            System.out.println("Hello World!!");
            String s1 = "a";
            String s2 = "b";
            String s3 = "c";
            String s4 = (new StringBuilder()).append(s1).append(s2).append(s3).toString();
            System.out.println(s4);
            System.out.println((new StringBuilder()).append(s1).append(" yo ").append(s2).toString());
\$\endgroup\$
2
  • \$\begingroup\$ Hi. Welcome to Code Review! This may be insightful, but how does it relate to the question? I.e. what changes in the posted code would you make? \$\endgroup\$ Commented May 31, 2016 at 11:25
  • \$\begingroup\$ As per my understanding, the query asked was to create strings in an optimize way. e.g. while printing logs we append too many strings using +. So above method was appending the strings using StringBuilder() But when I decompiled the code the java compiler was doing this optimzation itself. \$\endgroup\$ Commented May 31, 2016 at 13:58
1
\$\begingroup\$

@coderodde has a good point about eliminating the need for white space.

I'd simply do it this way:

private static String buildString(Object... values) {
        if (values.length == 0) {
             return "";
        }
        StringBuilder result = new StringBuilder();
        for (Object value : values) {
            result.append(' ').append(value);
        }
        return result.substring(1);
}
\$\endgroup\$
1
  • \$\begingroup\$ Nice Suggestion. Thanx! \$\endgroup\$ Commented May 27, 2016 at 15:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.