Over the years there have been no shortage of ways to format a string in java. What with the + operator, StringBuffer
, StringBuilder
, String.format(..)
and various specialised formatters for numbers and dates we sometimes feel a little spoilt for choice. But how do they all work and what are their advantanges / disadvantages?
StringBuffer
is a synchronized object! Yes, everything you do with it will cause synchronization. This is for historic reasons, unless you actually want this side effect use StringBuilder
which has the same methods without the overhead.
This object provides a simple way to concatenate various types. See the example below that uses StringBuilder to concatenate a String, char and a String:
public class Formatting
{
public static void main(String[] args)
{
final int DEFAULT_SIZE = 100;
StringBuilder sb = new StringBuilder(DEFAULT_SIZE);
sb.append("Hello");
sb.append(' ');
sb.append("World");
System.out.println(sb.toString());
}
}
Note that when I construct the object I pass in the desired capacity, this is because the default size of a StringBuilder is 16 characters, so to grow to 256 characters would take several re-allocations.
For tne vast majority of code, nothing whatsoever, as long as its readable. Unless you are in a critical section of code, there probably little wrong with just adding strings together using the + and += operator. For example, the slight overhead of doing this would need to happen very frequently to have significant impact. In addition, I believe that if used carefully it does not make the code less readable. For some time java compilers have optimised this out into a series of calls to StringBuilder. Just note the above problem, with the default size of StringBuilder
as this applies here to.
java.util.Formatter
and String.format(..)
were introduced in Java 1.5. These provide functionality similar to printf in C++ (actually a bit more like sprintf). We will always use String.format
in this example. For those familiar with printf, you can skip the next paragraph.
Using printf for formatting in C made some tasks very simple, hence why its made a comeback several years later in Java. Many of the runtime disadvantages associated with printf in C do not have the same consequences in Java. For example parameter mismatch was a serious problem in C, but in Java can be handled via an exception. However, one disadvantage of using this is that the String must be parsed each time the method is called.
Format works by parsing the format string (first parameter), and for each escape (%
public class Formatting
{
public static void main(String[] args)
{
int iVal = 10;
long lVal = 30;
double dVal = 3.5;
// simple example just print an integer, double and long.
String simpleFmt = String.format("Values: %d %f %d", iVal, dVal, lVal);
System.out.println(simpleFmt);
// Complex formatting example using same variables as above
// %04d - integer with 4 places zero padded.
// %.2f - floating point to two decimal places after point.
// %9d - integer padded to 9 places not zero padded.
String specificFmt = String.format("Values: %04d %.2f %9d", iVal, dVal, lVal);
System.out.println(specificFmt);
}
}
Output:
Values: 10 3.500000 30
Values: 0010 3.50 30
Something to note, if you are using this in a tight loop is that the default construction for String.format
and the underlying formatter class allocates a buffer of only 16 characters. For most casual uses this is fine.
Notice that the line of first output does not contain any padding, and the floating point value is to 6 places of precision; these are the defaults when using format. However, the second line is somewhat different, notice the zero padding and space padding of the first and last item. Also note that the floating point value is to a lesser precision.