字符串拼接的三种方法
加号
concat方法
StringBuilder(或StringBuffer)的append方法
程序例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public class Main { public static void main(String[] args) { String str = "a"; long time = System.currentTimeMillis(); for (int i = 0; i < 50000; i++) { str += "c"; } System.out.println("加号所花费的时间:"); System.out.println(System.currentTimeMillis()-time); String str2 = "a"; time = System.currentTimeMillis(); for (int i = 0; i < 50000; i++) { str2.concat("c"); } System.out.println("cancat方法所花费的时间:"); System.out.println(System.currentTimeMillis()-time); time = System.currentTimeMillis(); StringBuilder stringBuilder = new StringBuilder("a"); for (int i = 0; i < 50000; i++) { stringBuilder.append("c"); } String str3 = stringBuilder.toString(); System.out.println("StringBuilder的append方法:"); System.out.println(System.currentTimeMillis()-time); } }
|
程序输出
append方法最快、concat次之、加号最慢
“+”方法
虽然编译器对字符串的加号做了优化,它会使用StringBuilder的append方法进行追加,而它最终通过toString方法转换成String字符串,上例中“+”拼接的代码即如下:
1
| str = new StringBuilder(str).append("JTZen9").toString();
|
它与纯粹地使用StringBuilder的append方法是不同的:
每趟循环都会创建一个StringBuilder对象
每次执行完毕都会调用toString方法将其转换为字符串
所以,就耗费了更多的时间。
concat方法
concat源代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| 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); }
|
整体是一个数组的拷贝,虽然在内存中是处理都是原子性操作,速度非常快,但是,最后的return语句创建一个新String对象,也就是每次concat操作都会创建一个新的String对象,这也是限制concat方法速度的原因。
append方法
append源代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| 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 AbstractStringBuilder appendNull() { int c = count; ensureCapacityInternal(c + 4); final char[] value = this.value; value[c++] = 'n'; value[c++] = 'u'; value[c++] = 'l'; value[c++] = 'l'; count = c; return this; } private void ensureCapacityInternal(int minimumCapacity) { if (minimumCapacity - value.length > 0) expandCapacity(minimumCapacity); }
|
整个append方法都在做字符数组的处理,加长,拷贝等,这些都是基本的数据处理,整个方法内并没有生成对象。只是最后toString返回一个对象而已。
题外
1 2
| String str = "My name is "; str = str + "JTZen9";
|
相当于 str = new StringBuilder(str).append(“JTZen9”).toString(); 也就是说,该str = str + “JTZen9”;语句执行完之后,总共有三个对象。
1
| String str = "My name is " + "JTZen9";
|
JVM会直接把str作为一个对象,即 “My name is JTZen9”
使用场景
大多数情况,我们使用“+”,符合编码习惯和我们的阅读
当在频繁进行字符串的运算(如拼接、替换、删除等),或者在系统性能临界的时候,我们可以考虑使用concat或append方法