1:使用“+”直接拼接
使用示例:
String str1 = "Hello";
String str2 = "world";
String str = str1 + "," + str2;
"+"其实是Java提供的一个语法糖。
通过反编译上述代码后,可以看到其底层实现是通过将String转换成StringBuilder后,使用append方法进行拼接处理的。如下所示:
String var1 = "Hello";
String var2 = "world";
(new StringBuilder()).append(var1).append(",").append(var2).toString();
当使用“+”时,如果是两个字面量拼接,编译器会在编译期间进行常量折叠。如下所示:
//进行常量折叠后变成 String s = "ab";
String s = "a" + "b";
2:concat
使用示例:
String str1 = "Hello";
String str2 = "world";
String str = str1.concat(str2);
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);
}
通过源码可以看到,concat的实现原理是通过字符数组拼接,new一个新的String。
3:使用StringBuilder的append方法
使用示例
StringBuilder str1 = new StringBuilder();
str1.append("hello");
str1.append("world");
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;
}
public StringBuilder append(String str) {
super.append(str);
return this;
}
通过源码可以看到StringBuilde继承了AbstractStringBuilder,使用的AbstractStringBuilder中的append方法。其实现原理是直接将需要拼接的字符串,复制到字符数组中,如果字符数组长度不够,则会进行扩展。
4:使用StringBuffer的append方法
使用示例:
StringBuffer str1 = new StringBuffer();
str1.append("hello");
str1.append("world");
StringBuffer的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;
}
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
通过源码可以看到,StringBuffer和StringBuilder一样,继承了AbstractStringBuilder,并使用其append方法进行拼接,但区别是StringBuffer中的append方法使用了synchronized进行声明,说明这是一个线程安全的方法。
效率比较:
public static void main(String[] args) {
long t1 = System.currentTimeMillis();
String str1 = "hello";
for(int i = 0 ; i < 100000 ; i++ ){
String str2 = String.valueOf(i);
str1 = str1 + str2;
}
long t2 = System.currentTimeMillis();
System.out.println(" + 拼接使用时间:" + (t2 - t1));
long t3 = System.currentTimeMillis();
String str3 = "hello";
for(int i = 0 ; i < 100000 ; i++ ){
String str2 = String.valueOf(i);
str3 = str3.concat(str2);
}
long t4 = System.currentTimeMillis();
System.out.println(" concat 拼接使用时间:" + (t4 - t3));
long t5 = System.currentTimeMillis();
StringBuffer str4 = new StringBuffer("hello");
for(int i = 0 ; i < 100000 ; i++ ){
String str2 = String.valueOf(i);
str4 = str4 .append(str2);
}
long t6 = System.currentTimeMillis();
System.out.println(" StringBuffer.append() 拼接使用时间:" + (t6 - t5));
long t7 = System.currentTimeMillis();
StringBuilder str5 = new StringBuilder("hello");
for(int i = 0 ; i < 100000 ; i++ ){
String str2 = String.valueOf(i);
str5 = str5 .append(str2);
}
long t8 = System.currentTimeMillis();
System.out.println(" StringBuilder.append() 拼接使用时间:" + (t6 - t5));
}
输出结果:
+ 拼接使用时间:14036
concat 拼接使用时间:3793
StringBuffer.append() 拼接使用时间:5
StringBuilder.append() 拼接使用时间:5
StringBuilder <= StringBuffer < concat < +
《阿里巴巴java开发手册》中建议,在循环体内禁止使用“+”进行字符串拼接
总结+使用推荐
如果是在循环体内进行拼接,则使用StringBuffer或StringBuilder。
简单的字符串拼接,直接使用“+”即可。