I am wondering if anyone could give me an answer as to which one of these statements would perform better in java using StringBuilder
object:
Using
.append(string1 + string 2)
vs
.append(string1).append(string2)
I am wondering if anyone could give me an answer as to which one of these statements would perform better in java using StringBuilder
object:
Using
.append(string1 + string 2)
vs
.append(string1).append(string2)
The second option will almost certainly be superior (assuming there is any noticeable performance difference at all). When you write something like
string1 + string2
it is internally translated to
new StringBuilder(string1).append(string2).toString()
i.e. a new StringBuilder
is created to concatenate the strings. Your second variant circumvents this issue since it appends directly to the existing StringBuilder
, avoiding the creation of a new one.
We can take a look at the bytecode for each option:
public class Concat {
private static String s1 = "foo";
private static String s2 = "bar";
public static String good() {
StringBuilder b = new StringBuilder();
b.append(s1).append(s2);
return b.toString();
}
public static String bad() {
StringBuilder b = new StringBuilder();
b.append(s1 + s2);
return b.toString();
}
}
$javap -c Concat.class
public static java.lang.String good();
Code:
0: new #2 // class java/lang/StringBuilder
3: dup
4: invokespecial #3 // Method java/lang/StringBuilder."<init>":()V
7: astore_0
8: aload_0
9: getstatic #4 // Field s1:Ljava/lang/String;
12: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
15: getstatic #6 // Field s2:Ljava/lang/String;
18: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: pop
22: aload_0
23: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
26: areturn
public static java.lang.String bad();
Code:
0: new #2 // class java/lang/StringBuilder
3: dup
4: invokespecial #3 // Method java/lang/StringBuilder."<init>":()V
7: astore_0
8: aload_0
9: new #2 // class java/lang/StringBuilder
12: dup
13: invokespecial #3 // Method java/lang/StringBuilder."<init>":()V
16: getstatic #4 // Field s1:Ljava/lang/String;
19: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
22: getstatic #6 // Field s2:Ljava/lang/String;
25: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
28: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
31: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
34: pop
35: aload_0
36: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
39: areturn
Your first option actually becomes append(new StringBuilder().append(s1).append(s2).toString())
.
The first one is quicker to type and in many situations easier to read.
The second one may perform marginally better (as per Jeffrey's bytecode and arshajii's explanation).
However, this kind string concatenation is very unlikely to be the bottleneck in your system! If performance is a problem, you need to profile. Compilers differ. And improving algorithms generally has much, much more impact than this kind of micro-optimization.
Don't optimize earlier than necessary! Really! It's so tempting and such a waste of time.
It may be reasonably expected that a future improvement in the compiler will make both alternatives generate the same code.