Skip to content

字符串拼接使用 + 和 StringBuilder 的区别

说明

以下代码示例中使用的JDK版本是1.8

在平时开发中不知道大家有没有听到过一个规范,那就是在字符串拼接的时候,尽量使用 StringBuilder 而不是使用 +,但是在某些场景下使用StringBuilder的方式进行字符串拼接时,idea会给出警告,建议使用 String 来代替 StringBuilder ,如下图所示,那么为什么会出现这种情况呢?

string-join-difference-1.png

1、普通拼接

普通的几个字符串使用+拼接成一个字符串,因为老版本教程的原因,当前依旧有许多人拼接字符串时认为使用+会很消耗性能,推荐使用StringBuilder。实际上并不是这样,因为从JDK5开始,Java编译器就对此做了优化,当使用+拼接字符串时,编译器会自动将其转换成StringBuilder进行拼接。

为了验证该说法,我们新建一个测试类StringTest.java,代码如下:

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查看编译后的字节码,如下图所示:

string-join-difference-2.png

从图中可以看出,两种方式编译后的字节码是相同的,都是使用StringBuilder进行拼接,所以使用+拼接字符串和StringBuilder拼接字符串的性能差异几乎可以忽略不计,这也就是idea从代码简洁便于阅读的方向出发,建议使用+拼接字符串的原因。

2、循环拼接

在循环中拼接字符串时,使用+拼接字符串和StringBuilder拼接字符串的性能差异就很大了。因为使用+拼接字符串时,每次循环都会创建一个新的StringBuilder对象,如果循环次数太多时,还有可能出现内存泄漏的风险,而使用StringBuilder拼接字符串时,只会创建一个StringBuilder对象,所以在循环中拼接字符串时,使用StringBuilder拼接字符串的性能会更好。代码如下:

java
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的方式来拼接,执行效率更高。