Java开发手册中为什么不建议在for循环中使用“+“进行字符串操作

场景

java开发手册中对于循环体中进行字符串的拼接要求如下:

【推荐】循环体内,字符串的连接方式,使用 StringBuilder 的 append 方法进行扩展。

说明:下例中,反编译出的字节码文件显示每次循环都会 new 出一个 StringBuilder 对象,然后进行 append操作,

最后通过 toString 方法返回 String 对象,造成内存资源浪费。

并且还提供了反例:

   String str = "start";
    for (int i = 0; i < 100; i++) {
         str = str + "hello";
    }

Java中字符串占位替换、字符串拼接、字符串与Collection互转的方式:

Java中字符串占位替换、字符串拼接、字符串与Collection互转的方式_霸道流氓气质的博客-CSDN博客

字符串的拼接的几种方式可以参考上面的博客。

除了使用+拼接字符串之外,还可以使用 String 类中的方法 concat 方法来拼接字符串。

示例代码:

        String a = "a";
        String b = "b";
        String c = a.concat(b);
        System.out.println(c);

注:

博客:
霸道流氓气质的博客_CSDN博客-C#,架构之路,SpringBoot领域博主

下面看一下Java中String的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);
        //    }

首先创建一个字符数组,长度是已有字符串和待拼接字符串的长度之和,再把两个字符串的值复制到新的字符数组中,

并用这个字符数组创建一个新的String对象并返回。

为了验证上面for循环中让使用StringBuilder,而不让使用+,编写以下代码并对比耗时

        try(Cost cost = new Cost()){
            String aa = "aa";
            for (int i = 0; i < 100000; i++) {
               aa+="bb";
            }
        }

        try(Cost cost = new Cost()){
            StringBuilder aa = new StringBuilder();
            for (int i = 0; i < 100000; i++) {
                aa.append("bb");
            }
        }

耗时输出结果如下

        //cost:11565
        //cost:1

注意这里的代码耗时统计的方式可以参考

Java实战-基于JDK的LRU算法实现、优雅的实现代码耗时统计(Spring AOP、AutoCloseable方式):

Java实战-基于JDK的LRU算法实现、优雅的实现代码耗时统计(Spring AOP、AutoCloseable方式)_霸道流氓气质的博客-CSDN博客

分析原因:

在for循环中,每次都是new了一个StringBuilder,然后再把String转成StringBuilder,再进行append。

而频繁的新建对象当然要耗费很多时间了,不仅仅会耗费时间,频繁的创建对象,还会造成内存资源的浪费。

为了验证以上原因,我们对使用+进行拼接字符串的代码进行反编译查看

 

总结:

经过对比,我们发现,直接使用StringBuilder的方式是效率最高的。

因为StringBuilder天生就是设计来定义可变字符串和字符串的变化操作的。

但是,还要强调的是:

 1.如果不是在循环体中进行字符串拼接的话,直接使用+就好了。

2.如果在并发场景中进行字符串拼接的话,要使用StringBuffer来代替StringBuilder

猜你喜欢

转载自blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/131054153