Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to build a Java String using an SLF4J-style formatting function?

I've heard that using StringBuilder is faster than using string concatenation, but I'm tired of wrestling with StringBuilder objects all of the time. I was recently exposed to the SLF4J logging library and I love the "just do the right thing" simplicity of its formatting when compared with String.format. Is there a library out there that would allow me to write something like:

int myInteger = 42;
MyObject myObject = new MyObject();  // Overrides toString()
String result = CoolFormatingLibrary.format("Simple way to format {} and {}",
    myInteger, myObject);

Also, is there any reason (including performance but excluding fine-grained control of date and significant digit formatting) why I might want to use String.format over such a library if it does exist?

like image 566
BD at Rivenhill Avatar asked Jun 24 '10 21:06

BD at Rivenhill


3 Answers

Although the Accepted answer is good, if (like me) one is interested in exactly Slf4J-style semantics, then the correct solution is to use Slf4J's MessageFormatter

Here is an example usage snippet:

public static String format(String format, Object... params) {
    return MessageFormatter.arrayFormat(format, params).getMessage();
}

(Note that this example discards a last argument of type Throwable)

like image 151
Amir Abiri Avatar answered Oct 19 '22 17:10

Amir Abiri


For concatenating strings one time, the old reliable "str" + param + "other str" is perfectly fine (it's actually converted by the compiler into a StringBuilder).

StringBuilders are mainly useful if you have to keep adding things to the string, but you can't get them all into one statement. For example, take a for loop:

String str = "";
for (int i = 0; i < 1000000; i++) {
    str += i + " "; // ignoring the last-iteration problem
}

This will run much slower than the equivalent StringBuilder version:

StringBuilder sb = new StringBuilder(); // for extra speed, define the size
for (int i = 0; i < 1000000; i++) {
    sb.append(i).append(" ");
}
String str = sb.toString();

But these two are functionally equivalent:

String str = var1 + " " + var2;
String str2 = new StringBuilder().append(var1).append(" ").append(var2).toString();

Having said all that, my actual answer is:

Check out java.text.MessageFormat. Sample code from the Javadocs:

int fileCount = 1273;
String diskName = "MyDisk";
Object[] testArgs = {new Long(fileCount), diskName};

MessageFormat form = new MessageFormat("The disk \"{1}\" contains {0} file(s).");

System.out.println(form.format(testArgs));

Output:

The disk "MyDisk" contains 1,273 file(s).

There is also a static format method which does not require creating a MessageFormat object.

All such libraries will boil down to string concatenation at their most basic level, so there won't be much performance difference from one to another.

like image 28
Michael Myers Avatar answered Oct 19 '22 16:10

Michael Myers


Plus it worth bearing in min that String.format() is a bad implementation of sprintf done with regexps, so if you profile your code you will see an patterns and int[] that you were not expecting. MessageFormat and the slf MessageFormmater are generally faster and allocate less junk

like image 26
c_edward Avatar answered Oct 19 '22 17:10

c_edward