java字符串拼接的几种方式和区别【转载】

2020-05-02  本文已影响0人  CharlesNg

结论:
1.使用StringBuilder的方式是效率最高的。
2.如果不是在循环体中进行字符串拼接的话,直接使用+就好了。
3.如果在并发场景中进行字符串拼接的话,要使用StringBuffer来代替StringBuilder。

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

反编译后的内容如下:

String wechat = "Hollis";
String introduce = "\u6BCF\u65E5\u66F4\u65B0Java\u76F8\u5173\u6280\u672F\u6587\u7AE0";//每日更新Java相关技术文章
String hollis = (new StringBuilder()).append(wechat).append(",").append(introduce).toString();

通过查看反编译以后的代码,我们可以发现,原来字符串常量在拼接过程中,是将String转成了StringBuilder后,使用其append方法进行处理的。那么也就是说,Java中的+对字符串的拼接,其实现原理是使用StringBuilder.append。

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对象并返回。通过源码我们也可以看到,经过concat方法,其实是new了一个新的String。

StringBuffer sb1 = new StringBuffer("aaa");
String str1 = "bbb";
StringBuffer sb2 = sb1.append(",").append(str1);
StringBuilder sb1 = new StringBuilder("aaa");
String str1 = "bbb";
StringBuilder sb2= sb1 .append(",").append(str1 );

看看StringBuffer和StringBuilder的实现原理。
和String类类似,StringBuilder类也封装了一个字符数组,定义如下:

char[] value;

与String不同的是,它并不是final的,所以他是可以修改的。另外,与String不同,字符数组中不一定所有位置都已经被使用,它有一个实例变量,表示数组中已经使用的字符个数,定义如下:

int count;

其append源码如下:

public StringBuilder append(String str) {
    super.append(str);
    return this;
}

该类继承了AbstractStringBuilder类,看下其append方法:

public AbstractStringBuilder append(String str) {
    if (str == null)
        return appendNull();
    int len = str.length();
    ensureCapacityInternal(count + len);
    str.getChars(0, len, value, count);
    count += len;
    return this;
}

append会直接拷贝字符到内部的字符数组中,如果字符数组长度不够,会进行扩展。
StringBuffer和StringBuilder类似,最大的区别就是StringBuffer是线程安全的,看一下StringBuffer的append方法。

public synchronized StringBuffer append(String str) {
    toStringCache = null;
    super.append(str);
    return this;
}

该方法使用synchronized进行声明,说明是一个线程安全的方法。而StringBuilder则不是线程安全的。

上一篇 下一篇

猜你喜欢

热点阅读