Stringbuilder/Stringbuffer VS. "+" Operator

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 the String concatenation is equivalent to manually use StringBuilder.
  • On method3 the String concatenation is definitely bad as the compiler is creating a second StringBuilder 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 because StringBuffer 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



Leave a reply



Submit