进行字符串拼接时,经常会用到"+", 偶尔也用到string.concat去做,但官方推荐使用StringBuilder.append()去做,那这三种方式到底有什么区别呢?
我们先看string.concat源码:
public String concat(String str) {
int otherLen = str.length();
if (otherLen == 0) {
return this;
}
int len = value.length;
char buf[] = Arrays.copyOf(value, len + otherLen);
str.getChars(buf, len);
return new String(buf, true);
}
从源码可以看出进行了2次数组拷贝,每次回产生新的String对象。
StringBuilder.append源码:
StringBuilder.append方法:
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0, len, value, count);
count += len;
return this;
}
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0) {
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));
}
}
同样进行了2次数组拷贝,并返回StringBuider对象,整个过程未产生新的对象。
String +编译过程:
Code:
0: ldc #2 // String hi
2: astore_1
3: new #3 // class java/lang/StringBuilder
6: dup
7: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
10: aload_1
11: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
14: ldc #6 // String ni hao
16: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
22: astore_1
23: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
26: aload_1
27: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
30: new #3 // class java/lang/StringBuilder
33: dup
34: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
37: aload_1
38: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
41: ldc #10 // String chinese
43: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
46: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
49: astore_1
50: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
53: aload_1
54: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
57: return
通过编译器的优化,“+”会被StringBuilder优化,进行append操作,然后进行toString(),返回最终字符串,但对于多次的+操作后,会多次生成StringBuilder对象。
总结:
对于小于1万次的字符串拼接操作,三种方式区别不大;
大于1万以上,甚至10万或百万级别数据量,推荐apend操作。