Java 8中字符串拼接新姿势:StringJoiner

本文由码农网 –
小峰原创翻译,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划!

如果你想知道一共有多少种方法可以进行字符串拼接,教你一个简单的办法,在Intellij
IDEA中,定义一个Java
Bean,然后尝试使用快捷键自动生成一个toString方法,IDEA会提示多种toString生成策略可供选择。

终于,Java
8在java.util软件包下发布了StringJoiner类。我认为相对于我们使用StringBuffer
/
StringBuilder的旧式做法来连接字符串,这并非是一个迥然不同的实现。我们一起来看一看StringJoiner的用法和它的内部实现。

目前我使用的IDEA的toString生成策略默认的是使用JDK
1.8提供的StringJoiner。

例如,我有两个字符串为“Smart”和“Techie”,我想连接这些字符串为[Smart,Techie]。在这种情况下,我的前缀为“[”,后缀为“]”,以及分隔符为“,”。
StringJoiner有如下两个构造函数。

StringJoiner是java.util包中的一个类,用于构造一个由分隔符分隔的字符序列,并且可以从提供的前缀开始并以提供的后缀结尾。虽然这也可以在StringBuilder类的帮助下在每个字符串之后附加分隔符,但StringJoiner提供了简单的方法来实现,而无需编写大量代码。

StringJoiner(CharSequence delimiter)

StringJoiner(CharSequence delimiter, CharSequence prefix, CharSequence suffix)

StringJoiner类共有2个构造函数,5个公有方法。其中最常用的方法就是add方法和toString方法,类似于StringBuilder中的append方法和toString方法。

我们想要有前缀和后缀,因此在例子中使用第二个构造函数。

StringJoiner的用法比较简单,下面的代码中,我们使用StringJoiner进行了字符串拼接。

StringJoiner sjr = new StringJoiner(",", "[", "]");
sjr.add("Smart").add("Techie");
System.out.println("The final Joined string is " + sjr);

public class StringJoinerTest {

如果我们不希望有前缀和后缀,那么就:

public static void main(String[] args) {

sjr1.add("Smart").add("Techie");
System.out.println("The final Joined string is " + sjr1);

StringJoiner sj = new StringJoiner;

现在,我们将看到add和toString()方法的实现。

sj.add(“hollischuang”);

public StringJoiner add(CharSequence newElement) {
   prepareBuilder().append(newElement);
   return this;
}

sj.add;

prepareBuilder()实现如下。

System.out.println(sj.toString;

private StringBuilder prepareBuilder() {
    if (value != null) {
       value.append(delimiter);
    } else {
       value = new StringBuilder().append(prefix);
    }
    return value;
}

StringJoiner sj1 = new StringJoiner(“:”,”[“,”]”);

从上面的实现中,可以很明显看到StringJoiner遵循老式的做法。

sj1.add.add(“hollischuang”).add;

toString()实现如下。

System.out.println(sj1.toString;

public String toString() {
    if (value == null) {
      return emptyValue;
    } else {
    if (suffix.equals("")) {
      return value.toString();
    } else {
    int initialLength = value.length();
    String result = value.append(suffix).toString();
    // reset value to pre-append initialLength
    value.setLength(initialLength);
    return result;
    }
}

}

学习快乐!

}

以上代码输出结果:

hollischuangHollisJava干货

[Hollis:hollischuang:Java干货]

值得注意的是,当我们StringJoiner(CharSequence
delimiter)初始化一个StringJoiner的时候,这个delimiter其实是分隔符,并不是可变字符串的初始值。

StringJoiner(CharSequence delimiter,CharSequence prefix,CharSequence
suffix)的第二个和第三个参数分别是拼接后的字符串的前缀和后缀。

介绍了简单的用法之后,我们再来看看这个StringJoiner的原理,看看他到底是如何实现的。主要看一下add方法:

public StringJoiner add(CharSequence newElement) {

prepareBuilder().append(newElement);

return this;

}

private StringBuilder prepareBuilder() {

澳门新葡亰网站注册,if (value != null) {

value.append(delimiter);

} else {

value = new StringBuilder().append;

}

return value;

}

看到了一个熟悉的身影——StringBuilder
,没错,StringJoiner其实就是依赖StringBuilder实现的,在为什么阿里巴巴不建议在for循环中使用”+”进行字符串拼接中我们介绍过StringBuilder的实现原理,本文不在赘述。

当我们发现StringJoiner其实是通过StringBuilder实现之后,我们大概就可以猜到,他的性能损耗应该和直接使用StringBuilder差不多!

在了解了StringJoiner的用法和原理后,可能很多读者就会产生一个疑问,明明已经有一个StringBuilder了,为什么Java
8中还要定义一个StringJoiner呢?到底有什么好处呢?

如果读者足够了解Java 8的话,或许可以猜出个大概,这肯定和Stream有关。

作者也在Java doc中找到了答案:

A StringJoiner may be employed to create formatted output from a Stream
using Collectors.joining(CharSequence)

试想,在Java中,如果我们有这样一个List: