美文网首页
2019-09-05

2019-09-05

作者: 清风乀月 | 来源:发表于2019-09-16 16:51 被阅读0次

作者来源1
作者来源2

一、字符串拼接方式:+和concat和StringBuilder

源码:

public static void main(String[] args) {

        String str = "";

        System.out.println("执行加号拼接:");
        long starttime = System.currentTimeMillis();
        System.out.println("执行拼接之前的时间:"+starttime);
        for (int i = 0; i < 50000; i++) {
            str += "a";
        }
        long latertime = System.currentTimeMillis();
        System.out.println("执行拼接之后的时间:"+latertime);
        System.out.println("用加号拼接所花费的时间:"+(latertime - starttime));
        System.out.println("result== " + str);
        System.out.println("--------------------------------");


        String str1 = "";
        System.out.println("执行concat拼接:");
        long starttime1 = System.currentTimeMillis();
        System.out.println("执行拼接之前的时间:"+starttime1);
        for (int i = 0; i < 50000; i++) {
            str1 = str1.concat("b");
        }
        long latertime1 = System.currentTimeMillis();
        System.out.println("执行拼接之后的时间:"+latertime1);
        System.out.println("用加号拼接所花费的时间:"+(latertime1 - starttime1));
        System.out.println("result=="+str1);
        System.out.println("--------------------------------");

        StringBuilder stringBuilder = new StringBuilder();
        System.out.println("执行StringBuilder拼接:");
        long starttime2 = System.currentTimeMillis();
        System.out.println("执行拼接之前的时间:"+starttime2);
        for (int i = 0; i < 50000; i++) {
            stringBuilder.append("c");
        }
        long latertime2 = System.currentTimeMillis();
        System.out.println("执行拼接之后的时间:"+latertime2);
        System.out.println("用加号拼接所花费的时间:"+(latertime2 - starttime2));
        System.out.println("result=="+stringBuilder.toString());


    }

执行结果图:


image.png

由此可见,StringBuilder最快,concat次之,加号拼接最慢。

二、为什么会出现这样的情况

2.1 "+"方法实现原理

内部实现采用StringBuilder的append方法进行追加,最终以toString方法转换成String字符串,比如:

String wechat = "Hollis";
String introduce = "每日更新Java相关技术文章";
String hollis = wechat + "," + introduce;

反编译后的结果如下,反编译工具为jad。

String wechat = "Hollis";
String introduce = "\u6BCF\u65E5\u66F4\u65B0Java\u76F8\u5173\u6280\u672F\u6587\u7AE0";
String hollis = (new StringBuilder()).append(wechat).append(",").append(introduce).toString();

通过查看反编译后的代码,我们可以发现,在拼接字符串常量中,是将String转成了StringBuilder后,使用其append方法进行处理,也就是说,,在java中使用“+”对字符串拼接,采用的原理是使用StringBuilder。
但是它与纯粹使用StringBuilder的append方法是不同的:
1、每次执行循环添加字符时,它都会创建一个StringBuilder对象,
2、每次执行完后都会调用toString方法将其转换为字符串
所以耗费了更多时间。

2.2 "concat"方法实现原理

concat源代码

    public String concat(String str) {
        int otherLen = str.length();//获取添加的字符串长度
        if (otherLen == 0) {//如果字符串长度为0,则返回字符串长度本身
            return this;
        }
        int len = value.length;//获取原字符串的字符数组的长度
        char buf[] = Arrays.copyOf(value, len + otherLen);//将原字符串的字符数组放到buff数组中
        str.getChars(buf, len);//追加的字符串转化成字符数组,添加到buf中
        return new String(buf, true);//产生一个新的字符串返回
    }

整体的实现过程就是完成对数组的拷贝,虽然在内存中处理是原子性操作,速度非常快,但是,最后的return语句创建一个新的String对象,也就是每次concat操作都会创建一个新的String对象,这也是限制concat方法速度的原因。

2.3 "append"方法实现原理

代码实现

    public AbstractStringBuilder append(String str) {
        if (str == null)//如果是null值,则把null作为字符串处理
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len);//追加后的字符数组长度是否超过当前值
        str.getChars(0, len, value, count);//将字符串复制到目标数组
        count += len;
        return this;
    }
    private AbstractStringBuilder appendNull() {
        int c = count;
        ensureCapacityInternal(c + 4);
        final char[] value = this.value;
        value[c++] = 'n';
        value[c++] = 'u';
        value[c++] = 'l';
        value[c++] = 'l'; //将null添加到char[] value数组中
        count = c; //将count的值初始化
        return this;//返回结果
    }
    private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));//加长数组空间,并作数组拷贝
        }
    }

append方法都在做字符数组的处理,加长,拷贝等,这些都是基本的数据处理,整个方法内并没有生成对象,只是最后执行了toString方法返回了一个对象而已

三、题外

String str = "My name is ";
str = str + "JTZen9";

相当于str = new StringBuilder(str).append("JTZen9").toString();
也就是说,该str = str + "JTZen9",语句执行完后,总共有三个对象

String str = "My name is " + "JTZen9";

JVM会直接把str作为一个对象,即“My name is JTZen9”

四、使用场景

1、大多数情况,我们使用“+”,符合编码习惯和我们的阅读
2、当在频繁进行字符串的运算(如拼接、替换、删除等),或者在系统性能临界的时候,我们可以考虑使用concat或append方法

相关文章

  • GDAS006-深入理解SummarizedExperiment

    title: GDAS006-深入理解SummarizedExperiment类date: 2019-09-05 ...

  • TED-004 情商高的人怎样说话

    分类:职场 时间:2019-09-05 片长:09:59 简介:How to speak so that peop...

  • Openlayers API整理

    Openlayers API整理 openlayers 发布于 2019-09-05 一、创建地图 1、地图Map...

  • GDAS007-管理与处理大量BED文件

    title: GDAS006-管理与处理大量BED文件date: 2019-09-05 12:0:00type: ...

  • GDAS005-基因组实验中的数据结构与管理

    title: GDAS005-基因组实验中的数据结构与管理date: 2019-09-05 12:0:00type...

  • 偶得

    街市闲信步 本想聚闲聊 你并无所兴 路遇长髯哥 艳羡求拍之 须臾约牌去 2019-09-05

  • 2019-09-05间歇跑1

    时间:2019-09-05 21:00 线路:马路绿道 成绩:间歇跑800米*6用时59分 感受:这些一直下雨,其...

  • 哭泣的画

    忘了,忘不了】哭泣的画 时间:2019-09-05 09:59:43 短文学:曾祥国残红 想呐喊,想狂奔,甚至想翻...

  • 人生智慧

    公园里的大雁 时间: 2019-09-05 作者:执笔言情 一群大雁落在公园的湖边,它们打算就在这里生活,到了秋天...

  • 2019-09-05

    过一种幸福完整的教育生活。 各位领导,各位同仁,大家好: 相信这段时间,我们每个学校的教学楼上都有这句话:“过一种...

网友评论

      本文标题:2019-09-05

      本文链接:https://www.haomeiwen.com/subject/hsidyctx.html