Allows you to edit Strings in
Java version 1.5 or later. In prior
JDK (Java Development Kit)
’s, use the slower StringBuffer.
StringBuilder.insert, delete and replace are fairly expensive
operations since they have to shift the everything past that point to make room or
squeeze up. With replace, if the replacement String is the same length as the one replaced, you don’t have
this problem.
To find out how many chars are in a StringBuilder
already use length( );
To reuse a StringBuilder use setLength( 0 );
If you know the precise length of the String you are
building in advance, usually you can build it more efficiently with a char[] ca and use new String( ca )
to convert the result.
Estimating Initial Size
It is important to get a good initial
estimate for the StringBuilder size. If you guess too
small, it will have to take time out to allocate a buffer double the size, copy over
the partially built String. Further, you will have two
char[] objects cluttering the heap instead of just one.
If you guess too large, you will nail down space needlessly for the internal buffer.
Here is some code to monitor your estimates, allowing you to monitor them. Tweak the
buffer sizes and permissible limits until your program stops emitting error messages
when it runs. If you don’t specify any size, the constructor will assume
16 bytes. Hint: sort the error messages and eliminate
duplicates before examining them.
I used this method to optimise the initial sizes of the StringBuilders used in the static macros program that expands the
macros used to generate the mindprod.com website. It does
a great many StringBuilder. appends, though it also does a fair bit of I/O as well, since it has
to read each file in the website. Here are the results:
Effect of StringBuilder Optimising
Effect of StringBuilder
Optimising |
|
Time Before Optimising |
Time After Optimising |
% improvement |
Sun |
27.5 sec |
24 sec |
13% |
Jet |
25 sec |
22.5 sec |
10% |
---|
A cleverer version of this program would collect the actual range of values
for each StringBuilder and report them, along with a
report on which bounds are dangerously tight or overly loose. It might even give you
an idea of the distribution so you could deliberately allow rare cases to be handled
outside the range. You could implement this fairly simply by logging the current
StringBuffer size and the call point values to a
CSV (Comma-Separated Value)
or DataOutputStream file, then sorting it and picking out
the low and high values. You could also do it, albeit more slowly, by looking up
database records and maintaining the lowest and highest length seen for each
StringBuilder. You would not want this turned on in production, but the simple bounds
check in checkStringBuilderEstimate has almost no
overhead.
FastCat
I wrote a much more efficient version of StringBuilder
that I call FastCat. Instead
of estimating how long the final String will be, you
estimate how many fragments you are going to glue together. It is usually quite easy
to get a very accurate estimate. FastCat then accumulates
references to the fragments and only when you use toString
does it allocate a buffer the precise size for the final String. It does not waste a byte. Perhaps some day the
JVM (Java Virtual Machine) may offer a way to create a new String without having to create a char[]
first and discard it, then FastCat would leave no garbage to be collected at all.
Which Tool to Use
- FastCat is the fastest choice when you are gluing
Strings together. It is not efficient for gluing individual characters together. It
requires you to know an accurate upper bound on the number of fragments, though I
suppose you could write a version that did not.
- StringBuilder is the usual choice, preferably with
an high-side estimate of the final length.
- StringBuffer is for old JDKs (Java Development Kits).
You need to use it for regex search/replace.
- StringWriter is for when you have code that was
originally designed to write files.
- You can use a ByteArrayOutputStream as a sort of
StringBuilder for byte[].
Learning More
Oracle’s Javadoc on
StringBuilder class : available:
Oracle’s Javadoc on
String class : available:
You can get the compiler to do a number of optimisations with StringBuilder if you use the -XX:+OptimizeStringConcat javac compiler option.