进行字符串拼接时,经常会用到"+", 偶尔也用到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操作。
