I realize there is some benefit to constructing long Strings by using a StringBuffer object and then calling toString(), rather than repeatedly concatenating String objects.
I'm wondering though, if there is some rule about how many Strings are being concatenated that makes it easier to decide if I should use the StringBuffer method. If I'm just concatenating two strings, is it still beneficial to go through a StringBuffer first? If not two, then what is the limit? And does the number of characters have anything to do with it?
I don't think it matters that much if only a few or a few douzen strings are involved. However your application may be accessed by many users at the same time(like a servlet), then it may matter a little bit. You can set up a loop (10,000,000 times for example) to test this.
BJ - SCJP and SCWCD
We love Java programming. It is contagious, very cool, and lot of fun. - Peter Coad, Java Design
I believe there really is no lower limit. As soon as you do the first concat, the JVM creates a StringBuffer behind the scenes anyway...so even with just two, you might as well create it yourself since it's going to happen anyway.
Co-Author of <a href="http://www.oreilly.com/catalog/jswing2" target="_blank" rel="nofollow">Java Swing</a><br />Co-Creator of <a href="http://www.sun.com/training/catalog/courses/CX-310-055.xml" target="_blank" rel="nofollow">SCJP 5.0</a> and <a href="http://www.sun.com/training/certification/java/associate_beta.xml" target="_blank" rel="nofollow">SCJA</a> exams
IMO it's a trade-off between performance (and maybe memory efficiency) and convenience/clarity. If the part of your app doesn't require high performance do it which ever way is clearest/most convenient. If it does, use StringBuffer().
Originally posted by Julian Kennedy: IMO it's a trade-off between performance (and maybe memory efficiency) and convenience/clarity. If the part of your app doesn't require high performance do it which ever way is clearest/most convenient. If it does, use StringBuffer().
Good advice. As noted any String concatenation is turned into StringBuffer appendage by the compiler. I've seen timing tests showing that letting the compiler do the work turned out to be slightly faster.
However, if you're tuning for performance by using a StringBuffer, make sure you create it large enough to hold the entire concatenated String to avoid having to resize (create, copy, destroy) the buffer multiple times. In Java 1.3 and 1.4, the buffer starts at 16 characters by default and doubles* in capacity during a resize (unless more space is needed).
For example, if you concatenate a bunch of smallish Strings that come out to 500 characters, StringBuffer will create 6 buffers with lengths 16, 34, 70, 142, 286, and 574. It will also need to copy the contents from one to the next along the way. You can avoid all of that by using StringBuffer(600) or some value that you think will be enough.
* Instead of merely doubling, expandCapacity(int minimumCapacity) adds one to the current capacity and doubles the result. If this is smaller than minimumCapacity, it will use minimumCapacity instead.
Originally posted by David Harkness: Good advice. As noted any String concatenation is turned into StringBuffer appendage by the compiler. I've seen timing tests showing that letting the compiler do the work turned out to be slightly faster.
Do you have a reference for that? The bytecode for compiler-generated string concatenation looks to be identical to the code you'd get if you'd do it explicitly, but I might have missed something.
However, if you're tuning for performance by using a StringBuffer, make sure you create it large enough to hold the entire concatenated String to avoid having to resize [...] the buffer multiple times. [...] You can avoid all of that by using [...] some value that you think will be enough.
Are you sure you want to advise this? Because, as so often in attempts at Java string optimisation, there are subtle traps for the unwary. The trap in this case is that the char array that backs the StringBuffer is also going to back any String that you derive from the buffer. Someone reading your explanation might think "right, I'll just make sure my StringBuffer is always large enough" and find in the end that all his little Strings take up WAY more memory than they ought to.
Of course, when you know beforehand what size the buffer is going to grow to it's worth presizing it, but if you don't know exactly what the size is going to be then it's usually best to stay well clear.
Joined: Aug 07, 2003
Originally posted by Peter den Haan: Do you have a reference for that?
I couldn't find the original article (it was at least a year ago, probably two), but the difference 1) was extremely marginal in favor of + and 2) only applied to single-statement concatenation. I did, however, find some interesting related pages. Of course, there is no overall agreement, and everyone pretty much says "Always/Never use String/StringBuffer," so take your pick.
As with all advice, if you follow it blindly, bad things are likely to happen. I guess my first advice would be to make sure you need to optimize this in the first place. This is what we've all been saying, but it's worth saying again.
I would recommend checking out the StringBuffer source for those that are really curious. One of the links above mentioned that for JDK 1.4.1 SB was changed such that clearing it -- setLength(0) -- now makes a copy of the char buffer even though the old version of the JDK optimized this away. If you're clearing the buffer, certainly you don't need a copy of it to modify. Thus, in general, do not reuse StringBuffers once you've called toString() on them, pegging a String to its underlying buffer.
Seeking for your opinions. The following code was extracted from http://java.sun.com/developer/JDCTechTips/2002/tt0305.html#tip1. I'm not asking for performance issue since StringBuffer is definitely better than String in this case. What I'm asking is which approach is more readable in this example. Which approach do you prefer and why?
Originally posted by Joyce Lee: What I'm asking is which approach is more readable in this example. Which approach do you prefer and why?
I believe that as to the readability those 2 approaches are totaly equal because the examples are really short. I think this readability issue is more visible in examples like:
which would sprawl over 7 lines when using sb.append.
But I must explicitly mention that I do not advocate using Strings. For the above examples use of StringBuffer and append is a must.
Get a better web browser:<br /><a href="http://www.mozilla.org/products/firefox/switch.html" target="_blank" rel="nofollow">http://www.mozilla.org/products/firefox/switch.html</a>
Joined: Jul 11, 2003
Thanks Petr. I purposely used this example to seek for opinion. I've the same sentiment as you, both are equally the same in term of readability in above example. But still, some would still prefer one approach over the other and I would like to know why. For example, String approach may be preferable because StringBuffer has more lines. Or maybe, performance issue shouldn't take into consideration while coding.
I read the book "Better, Faster, Lighter Java" by Bruce A. Tate and Justin Gehtland. In this book, it advocates simplicity which I wholeheartedly agree. On page 25, it compares the readability between String and StringBuffer using the following example:
The author prefers String approach as it has lesser code. His advice: Trade a little less performance for better readability every time.
But what if I change the StringBuffer code to:
Neater. In term of readability, both look the same to me. In term of performance, can't notice the difference. In term of code size, StringBuffer has two more lines than the String approach. For in this case, I'd go for String approach.
Peter den Haan
Joined: Apr 20, 2000
Originally posted by Petr Blahos: I think this readability issue is more visible in examples like:which would sprawl over 7 lines when using sb.append.
But would it?I feel this is clearer, if only because the way I broke it up keeps the HTML tags together.
Some have religious objections to method chaining, but I think it's great in cases like this. Ditto for, say, Hibernate Criteria or a Spring ModelAndView and a couple of other APIs where this style is supported because it's a really convenient way to make lots of little method calls on the same object.
- Peter [ September 01, 2004: Message edited by: Peter den Haan ]
I realise these are examples guys but there's really no need to write HTML in Strings now that we have JSP, right? We don't want to go back to the mess that I've seen in pre-JSP servlet apps. It still surprises me that no one thought to use HTML templates.
Joined: Apr 28, 2004
Well, to be honest, I really don't feel like including a jsp engine in my small standalone swing application ;-) (Yes, that's where I use HTML).
But thanks for your idea about templates. A quick thought tells me that it is probably going to be slower than appends but I might give it a try.
Peter den Haan
Joined: Apr 20, 2000
Originally posted by Petr Blahos: But thanks for your idea about templates. A quick thought tells me that it is probably going to be slower than appends but I might give it a try.
It is slower, but that might not at all be important. Can I suggest you look at Velocity?