几种字符串拼接方式解析

一)简介

字符串拼接在程序中是很常用的,关键是需要了解各种字符串拼接方式原理,优先选择最好的字符串拼接方式。Java程序中提供了几种不同的拼接方式。

 

二)“+”号字符串拼接

“+”号字符串拼接是最简单方便的方式,刚学编程的时候,几乎都是用此方式。

1)字符串拼接方式

String s1 = "ouyangjun";
String s2 = "p812438109";
System.out.println(s1 + s2); // ouyangjunp812438109

2)反编译之后的源码

System.out.println(new StringBuilder(String.valueOf(s1)).append(s2).toString());

结论:编译时,先new一个StringBuilder对象,再把参数append到对象中,最后再toString。

3)字符串拼接方式

String s1 = "ouyangjun";
String s2 = "p812438109";
String s3 = "";
for (int i = 0; i < 10000; i++) {
    s3 += s1 + s2;
    System.out.println(s3);
}

4)反编译之后的源码

String s1 = "ouyangjun";
String s2 = "p812438109";
String s3 = "";
for (int i = 0; i < 10000; i++) {
    s3 = new StringBuilder(String.valueOf(s3)).append(s1).append(s2).toString();
    System.out.println(s3);
}

结论:在用"+"号拼接时,不管是什么方式拼接,都是会不断new StringBuilder对象。如循环次数越多,该拼接方式性能会越低,最终可能导致内存溢出等问题。现在程序中都不建议用该方式拼接字符串了。

 

三)StringBuffer字符串拼接

1)StringBuffer字符串拼接和反编译之后的源码是一样,没有太大的区别,如下。

StringBuffer buffer = new StringBuffer();
buffer.append("ouyangjun");
buffer.append("p812438109");
System.out.println(buffer); // ouyangjunp812438109
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < 10000; i++) {
    buffer.append("ouyangjun").append("p812438109");
    System.out.println(buffer);
}

2)StringBuffer中append源码

@Override
public synchronized StringBuffer append(String str) {
    toStringCache = null;
    super.append(str); // 调用了父类AbstractStringBuilder的append方法
    return this;
}

3)AbstractStringBuilder中append源码

public AbstractStringBuilder append(String str) {
    if (str == null) // 如果str是null, 就返回空
        return appendNull();
    int len = str.length(); // 获取字符串的长度
    ensureCapacityInternal(count + len); // 判断是否需要扩容
    str.getChars(0, len, value, count); // 获取一个新的char[]数组
    count += len; // 累加字符串的长度
    return this; // 返回append之后的字符串
}

结论:StringBuffer有synchronized修饰,说明是线程安全的,在程序中强调线程安全性,选择该方式。

 

四)StringBuilder字符串拼接

1)StringBuilder字符串拼接和反编译之后的源码是一样,没有太大的区别,如下。

StringBuilder builder = new StringBuilder();
builder.append("ouyangjun");
builder.append("p812438109");
System.out.println(builder); // ouyangjunp812438109
StringBuilder builder = new StringBuilder();
for (int i = 0; i < 10000; i++) {
    builder.append("ouyangjun").append("p812438109");
    System.out.println(builder);
}

2)StringBuilder中append源码

@Override
public StringBuilder append(String str) {
    super.append(str); // 调用了父类AbstractStringBuilder的append方法
    return this;
}

3)AbstractStringBuilder中append源码

public AbstractStringBuilder append(String str) {
    if (str == null) // 如果str是null, 就返回空
        return appendNull();
    int len = str.length(); // 获取字符串的长度
    ensureCapacityInternal(count + len); // 判断是否需要扩容
    str.getChars(0, len, value, count); // 获取一个新的char[]数组
    count += len; // 累加字符串的长度
    return this; // 返回append之后的字符串
}

结论:StringBuilder由于不是原子性的操作,也没有线程安全修饰符,说明不是线程安全的,在程序中不强调线程安全的情况,可选该方式。

 

五)StringJoiner字符串拼接

1)StringJoiner字符串拼接和反编译之后的源码是一样,区别在于该方式是用一个连接符把字符串拼接,如下。

StringJoiner joiner = new StringJoiner("-");
joiner.add("ouyangjun");
joiner.add("p812438109");
System.out.println(joiner); // 输出: ouyangjun-p812438109
StringJoiner joiner = new StringJoiner("-");
for (int i = 0; i < 10000; i++) {
    joiner.add("ouyangjun").add("p812438109");
    System.out.println(joiner);
}

2)StringJoiner中add源码

public StringJoiner add(CharSequence newElement) {
    prepareBuilder().append(newElement); // 调用父类StringBuilder的append方法
    return this;
}

private StringBuilder prepareBuilder() {
    if (value != null) {
        value.append(delimiter); // 在现有的StringBuilder基础上拼接字符串
    } else {
        value = new StringBuilder().append(prefix); // 字符串为null,直接new一个StringBuilder
    }
    return value;
}

结论:StringJoiner是实现了StringBuilder的append方法,也是一种线程不安全的字符串拼接方式。在程序中不强调线程安全,又需要通过某种连接符拼接字符串的时候,可选用该方式。

 

六)String中concat字符串拼接

1)concat字符串拼接方式,和反编译之后的源码差不多

String s1 = "ouyangjun";
String s2 = "p812428109";
System.out.println(s1.concat(s2));

String s3 = "";
for (int i = 0; i < 10000; i++) {
    s3 = s3.concat(s1).concat(s2);
    System.out.println(s3);
}

2)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); // 创建一个新的char[]数组存储str
    str.getChars(buf, len); // 把数组内容复制到str中
    return new String(buf, true); // 创建一个新的String对象返回
}

结论:String中concat拼接方式,会不断创建数组,和复制数据,再返回一个新的String对象,性能不是很好。

 

7)String中join字符串拼接

1)join字符串拼接方式

String s1 = "ouyangjun";
String s2 = "p812428109";
System.out.println(String.join("-", s1, s2));

2)反编译之后的源码

String s1 = "ouyangjun";
String s2 = "p812428109";
System.out.println(String.join("-", new CharSequence[]{s1, s2}));

结论:会先把字符串转换成一个CharSequence[]数组,再用连接符拼接字符串。

3)join字符串拼接方式

String s1 = "ouyangjun";
String s2 = "p812428109";
String s3 = "";
for (int i = 0; i < 10000; i++) {
    s3 = String.join("-", s1, s2, s3);
    System.out.println(s3);
}

4)反编译之后的源码

String s1 = "ouyangjun";
String s2 = "p812428109";
String s3 = "";
for (int i = 0; i < 10000; i++) {
    s3 = String.join("-", new CharSequence[]{s1, s2, s3});
    System.out.println(s3);
}

结论:在循环中使用String的join方式拼接字符串,也会不断创建String对象,性能不是很好。

 

八)字符串拼接方式总结

1)String中“+”号、concat、join这几种字符串拼接方式在循环中的场景下,都可能存在性能。如果只是单纯两两拼接的话,还可以选择使用该方式。

2)StringBuffer字符串拼接方式,适用于程序中强调线程安全的场景下。

3)StringBuilder字符串拼接方式,适用于程序中不强调线程安全的场景下。

4)StringJoiner字符串拼接方式,适用于程序中不强调线程安全,并需要把字符串用连接符连接场景下。

 

识别二维码关注个人微信公众号

本章完结,待续、欢迎转载!
 
本文说明:该文章属于原创,如需转载,请标明文章转载来源!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值