字符串拼接使用 + 和 StringBuilder 的区别
说明
以下代码示例中使用的JDK版本是1.8
在平时开发中不知道大家有没有听到过一个规范,那就是在字符串拼接的时候,尽量使用 StringBuilder
而不是使用 +
,但是在某些场景下使用StringBuilder的方式进行字符串拼接时,idea会给出警告,建议使用 String 来代替 StringBuilder ,如下图所示,那么为什么会出现这种情况呢?
1、普通拼接
普通的几个字符串使用+
拼接成一个字符串,因为老版本教程的原因,当前依旧有许多人拼接字符串时认为使用+
会很消耗性能,推荐使用StringBuilder
。实际上并不是这样,因为从JDK5开始,Java编译器就对此做了优化,当使用+
拼接字符串时,编译器会自动将其转换成StringBuilder
进行拼接。
为了验证该说法,我们新建一个测试类StringTest.java
,代码如下:
public class StringTest {
public String append1(int index) {
return "index: " + index;
}
public String append2(int index) {
return new StringBuilder().append("index: ").append(index).toString();
}
public static void main(String[] args) {
StringTest test = new StringTest();
long l1 = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
String str = test.append1(i);
}
long l2 = System.currentTimeMillis();
System.out.println("append1 use time: " + (l2 - l1)); // 输出:append1 use time: 35
long l3 = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
String sb = test.append2(i);
}
long l4 = System.currentTimeMillis();
System.out.println("append2 use time: " + (l4 - l3)); // 输出:append2 use time: 16
}
}
虽然两种方式有差异,但是差异很小。现在来看一下编译后的字节码,我们先使用javac StringTest.java
,将其转换成StringTest.class
文件,然后使用javap -c StringTest.class
查看编译后的字节码,如下图所示:
从图中可以看出,两种方式编译后的字节码是相同的,都是使用StringBuilder
进行拼接,所以使用+
拼接字符串和StringBuilder
拼接字符串的性能差异几乎可以忽略不计,这也就是idea从代码简洁便于阅读的方向出发,建议使用+
拼接字符串的原因。
2、循环拼接
在循环中拼接字符串时,使用+
拼接字符串和StringBuilder
拼接字符串的性能差异就很大了。因为使用+
拼接字符串时,每次循环都会创建一个新的StringBuilder
对象,如果循环次数太多时,还有可能出现内存泄漏的风险,而使用StringBuilder
拼接字符串时,只会创建一个StringBuilder
对象,所以在循环中拼接字符串时,使用StringBuilder
拼接字符串的性能会更好。代码如下:
public class StringTest {
public static void main(String[] args) {
long l1 = System.currentTimeMillis();
String str = "";
for (int i = 0; i < 100000; i++) {
str += "index: " + i;
}
long l2 = System.currentTimeMillis();
System.out.println("append1 use time: " + (l2 - l1)); // 输出: append1 use time: 71154
long l3 = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100000; i++) {
sb.append("index: ").append(i);
}
long l4 = System.currentTimeMillis();
System.out.println("append1 use time: " + (l4 - l3)); // 输出:append2 use time: 3
}
}
由此可以看出,在循环中拼接字符串时,使用StringBuilder
拼接字符串的性能会更好。
3、总结
- 在普通字符串拼接时,使用
+
的方式来拼接,代码更简洁。 - 在循环中拼接字符串时,使用
StringBuilder
的方式来拼接,执行效率更高。