为什么阿里巴巴Java开发手册中不建议在循环体中使用+进行字符串拼接?

之前在阅读《阿里巴巴Java开发手册》时,发现有一条是关于循环体中字符串拼接的建议,具体内容如下:

阿里巴巴Java开发手册

那么我们首先来用例子来看看在循环体中用 + 或者用 StringBuilder 进行字符串拼接的效率如何吧(JDK版本为 jdk1.8.0_201)。

public class StringConcatDemo {
    public static void main(String[] args) {
        long s1 = System.currentTimeMillis();
        new StringConcatDemo().addMethod();
        System.out.println("使用 + 拼接:" + (System.currentTimeMillis() - s1));

        s1 = System.currentTimeMillis();
        new StringConcatDemo().stringBuilderMethod();
        System.out.println("使用 StringBuilder 拼接:" + (System.currentTimeMillis() - s1));
    }

    public String addMethod() {
        String result = "";
        for (int i = 0; i < 100000; i++) {
            result += (i + "wupx");
        }
        return result;
    }

    public String stringBuilderMethod() {
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < 100000; i++) {
            result.append(i).append("wupx");
        }
        return result.toString();
    }
}

执行结果如下:

使用 + 拼接:29282
使用 StringBuilder 拼接:4

为什么这两种方法的时间会差这么多呢?接下来让我们一起进一步研究。

为什么 StringBuilder 比 + 快这么多?

从字节码层面来看下,为什么循环体中字符串拼接 StringBuilder 比 + 快这么多?

使用 javac StringConcatDemo.java 命令编译源文件,使用 javap -c StringConcatDemo 命令查看字节码文件的内容。

其中 addMethod() 方法的字节码如下:

public java.lang.String addMethod();
Code:
   0: ldc           #16                 // String
   2: astore_1
   3: iconst_0
   4: istore_2
   5: iload_2
   6: ldc           #17                 // int 100000
   8: if_icmpge     41
  11: new           #7                  // class java/lang/StringBuilder
  14: dup
  15: invokespecial #8                  // Method java/lang/StringBuilder."<init>":()V
  18: aload_1
  19: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  22: iload_2
  23: invokevirtual #18                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
  26: ldc           #19                 // String wupx
  28: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  31: invokevirtual #12                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
  34: astore_1
  35: iinc          2, 1
  38: goto          5
  41: aload_1
  

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

后端核心技术精讲 文章被收录于专栏

专注分享后端技术干货,包括 Java 基础、Java 并发、JVM、Elasticsearch、Zookeeper、Nginx、微服务、消息队列、源码解析、数据库、设计模式、面经等,助你编程之路少走弯路。

全部评论
原创不易,欢迎点赞、收藏、订阅三连!
点赞 回复 分享
发布于 2020-04-05 18:27

相关推荐

10-17 12:16
同济大学 Java
7182oat:快快放弃了然后发给我,然后让我也泡他七天最后再拒掉,狠狠羞辱他一把😋
点赞 评论 收藏
分享
1 收藏 评论
分享
牛客网
牛客企业服务