StringBuilder/StringBuffer vs. + Operator
Using String
concatenation is translated into StringBuilder
operations by the compiler.
To see how the compiler is doing I'll take a sample class, compile it and decompile it with jad to see what's the generated bytecode.
Original class:
public void method1() {
System.out.println("The answer is: " + 42);
}
public void method2(int value) {
System.out.println("The answer is: " + value);
}
public void method3(int value) {
String a = "The answer is: " + value;
System.out.println(a + " what is the question ?");
}
The decompiled class:
public void method1()
{
System.out.println("The answer is: 42");
}
public void method2(int value)
{
System.out.println((new StringBuilder("The answer is: ")).append(value).toString());
}
public void method3(int value)
{
String a = (new StringBuilder("The answer is: ")).append(value).toString();
System.out.println((new StringBuilder(String.valueOf(a))).append(" what is the question ?").toString());
}
- On
method1
the compiler performed the operation at compile time. - On
method2
theString
concatenation is equivalent to manually useStringBuilder
. - On
method3
theString
concatenation is definitely bad as the compiler is creating a secondStringBuilder
rather than reusing the previous one.
So my simple rule is that concatenations are good unless you need to concatenate the result again: for instance in loops or when you need to store an intermediate result.
Why is StringBuilder much faster than String?
Do you understand how it works internally?
Every time you do stringA += stringB;
a new string is created an assigned to stringA, so it will consume memory (a new string instance!) and time (copy the old string + new characters of the other string).
StringBuilder
will use an array of characters internally and when you use the .append()
method it will do several things:
- check if there are any free space for the string to append
- again some internal checks and run a
System.arraycopy
to copy the characters of the string in the array.
Personally, I think the allocation of a new string every time (creating a new instance of string, put the string, etc.) could be very expensive in terms of memory and speed (in while/for, etc. especially).
In your example, use a StringBuilder
is better, but if you need (example) something simple like a .toString()
,
public String toString() {
return StringA + " - " + StringB;
}
makes no differences (well, in this case it is better you avoid StringBuilder overhead which is useless here).
StringBuilder vs String concatenation in toString() in Java
Version 1 is preferable because it is shorter and the compiler will in fact turn it into version 2 - no performance difference whatsoever.
More importantly given we have only 3
properties it might not make a
difference, but at what point do you
switch from concat to builder?
At the point where you're concatenating in a loop - that's usually when the compiler can't substitute StringBuilder
by itself.
what is the significance of StringBuffer and which should be used more often, StringBuffer or StringBuilder?
In practice everybody should always use StringBuilder (and never use StringBuffer; often you don't really need StringBuilder because the compiler takes care of adding a helper to do this for you). The only reason StringBuffer is still around is for fear that taking it away would break some code somewhere. Java takes backward compatibility really seriously.
The difference between StringBuffer and StringBuilder is that the methods of StringBuffer are synchronized. That means each thread trying to call a synchronized method has to acquire the lock on the object, this prevents problems where two threads calling methods on the same object could result in the object's state becoming corrupted. The backing data store within the object is a dynamically-growing array, and if two threads are messing with it at the same time and one changes it out from under the other, bad things happen: exceptions get thrown, or worse, data gets stomped on silently.
It turns out that there is not a real life need for a string-building object that concatenates strings received concurrently from multiple threads, because nobody wants a string constructed in a way that makes it unpredictable what order the substrings show up in. It's overwhelmingly likely that when you want to construct a string (and have determined you do need a builder) that builder will be thread-confined (meaning only one thread can access the builder), so no synchronization is needed.
Codename One StringBuilder vs + operator between Strings
This is a mistake in the JavaDocs probably because they were derived from StringBuffer
as a starting point. StringBuilder
isn't threadsafe. I personally use the +
/ +=
operators which are both pretty efficient in current versions of javac (current being Java 8+).
The advantage of StringBuilder
is if you have something the compiler can't detect. E.g. if you have a string to which things are appended in a relatively long scope or even one that exceeds method boundaries. In that case the compiler will have to create multiple StringBuilder
and String
instances instead of a single instance of StringBuilder
. Since the compiler abstracts that you'd need to guess what it does and how smart it can be.
String, StringBuffer, and StringBuilder
Mutability Difference:
String
is immutable, if you try to alter their values, another object gets created, whereas StringBuffer
and StringBuilder
are mutable so they can change their values.
Thread-Safety Difference:
The difference between StringBuffer
and StringBuilder
is that StringBuffer
is thread-safe. So when the application needs to be run only in a single thread then it is better to use StringBuilder
. StringBuilder
is more efficient than StringBuffer
.
Situations:
- If your string is not going to change use a String class because a
String
object is immutable. - If your string can change (example: lots of logic and operations in the construction of the string) and will only be accessed from a single thread, using a
StringBuilder
is good enough. - If your string can change, and will be accessed from multiple threads, use a
StringBuffer
becauseStringBuffer
is synchronous so you have thread-safety.
String concatenation with operator + vs using stringbuffer?
First notice that the documentation you have linked is very old. Notice it's for Java 1.4.2.
J2SE 1.4.2 is in its Java Technology End of Life (EOL) transition period. The EOL transition period began Dec, 11 2006 and will complete October 30th, 2008, when J2SE 1.4.2 will have reached its End of Service Life (EOSL).
In newer versions of the documentation this statement has been removed. However another statement has been added that you should be aware of:
As of release JDK 5, this class has been supplemented with an equivalent class designed for use by a single thread, StringBuilder. The StringBuilder class should generally be used in preference to this one, as it supports all of the same operations but it is faster, as it performs no synchronization.
Secondly notice that the documentation you refer to has this code:
x = "a" + 4 + "c";
The 4
there isn't just a typo. Your example is different because the compiler will convert the code to use just a single string literal. These two lines are the same:
x = "a" + "b" + "c";
x = "abc";
The string literal will be interned.
But in the general case where the compiler cannot just use a single string literal, the compiler will transform the first version into the second, except it will use StringBuilder
instead because it is more efficient.
Related Topics
How to Write an Array to a File Java
Mocking Time in Java 8's Java.Time API
How to "Pretty Print" a Duration in Java
How to Redirect to Another Action Class Without Using on Struts.Xml
Does Adding a Jlabel to a JPAnel "Hide" the JPAnel
Try/Catch Versus Throws Exception
Pdfbox - Signature Validity Checkmark Not Visible in Acrobat Reader
Getting Value of Public Static Final Field/Property of a Class in Java via Reflection
Websphere All Logs Are Going to Systemout.Log
Java Gif Animation Not Repainting Correctly
Totally Confused with Java.Exe
Method Calls Inside a Java Class Return an "Identifier Expected After This Token" Error
Minimum Spring Version Compatible with Java 11