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

 更新时间:2019年09月05日 16:40:21   作者:hollischuang  
在本篇文章里小编给大家整理了关于Java 8中字符串拼接新姿势StringJoiner的详解内容,需要的朋友们参考下。

在为什么阿里巴巴不建议在for循环中使用”+”进行字符串拼接一文中,我们介绍了几种Java中字符串拼接的方式,以及优缺点。其中还有一个重要的拼接方式我没有介绍,那就是Java 8中提供的StringJoiner ,本文就来介绍一下这个字符串拼接的新兵。

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

11111

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

介绍

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

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

用法

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

public class StringJoinerTest {

  public static void main(String[] args) {
    StringJoiner sj = new StringJoiner("Hollis");

    sj.add("hollischuang");
    sj.add("Java干货");
    System.out.println(sj.toString());

    StringJoiner sj1 = new StringJoiner(":","[","]");

    sj1.add("Hollis").add("hollischuang").add("Java干货");
    System.out.println(sj1.toString());
  }
}

以上代码输出结果:

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(prefix);
  }
  return value;
}

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

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

为什么需要StringJoiner

在了解了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:

List<String> list = ImmutableList.of("Hollis","hollischuang","Java干货");

如果我们想要把他拼接成一个以下形式的字符串:

Hollis,hollischuang,Java干货

可以通过以下方式:

StringBuilder builder = new StringBuilder();

if (!list.isEmpty()) {
  builder.append(list.get(0));
  for (int i = 1, n = list.size(); i < n; i++) {
    builder.append(",").append(list.get(i));
  }
}
builder.toString();

还可以使用:

list.stream().reduce(new StringBuilder(), (sb, s) -> sb.append(s).append(','), StringBuilder::append).toString();

但是输出结果稍有些不同,需要进行二次处理:

Hollis,hollischuang,Java干货,

还可以使用”+”进行拼接:

list.stream().reduce((a,b)->a + "," + b).toString();

以上几种方式,要么是代码复杂,要么是性能不高,或者无法直接得到想要的结果。

为了满足类似这样的需求,Java 8中提供的StringJoiner就派上用场了。以上需求只需要一行代码:

list.stream().collect(Collectors.joining(":"))

即可。上面用的表达式中,Collectors.joining的源代码如下:

public static Collector<CharSequence, ?, String> joining(CharSequence delimiter,
                             CharSequence prefix,
                             CharSequence suffix) {
  return new CollectorImpl<>(
      () -> new StringJoiner(delimiter, prefix, suffix),
      StringJoiner::add, StringJoiner::merge,
      StringJoiner::toString, CH_NOID);
}

其实现原理就是借助了StringJoiner。

当然,或许在Collector中直接使用StringBuilder似乎也可以实现类似的功能,只不过稍微麻烦一些。所以,Java 8中提供了StringJoiner来丰富Stream的用法。

而且StringJoiner也可以方便的增加前缀和后缀,比如我们希望得到的字符串是[Hollis,hollischuang,Java干货]而不是Hollis,hollischuang,Java干货的话,StringJoiner的优势就更加明显了。

总结

本文介绍了Java 8中提供的可变字符串类——StringJoiner,可以用于字符串拼接。

StringJoiner其实是通过StringBuilder实现的,所以他的性能和StringBuilder差不多,他也是非线程安全的。

如果日常开发中中,需要进行字符串拼接,如何选择?

1、如果只是简单的字符串拼接,考虑直接使用”+”即可。

2、如果是在for循环中进行字符串拼接,考虑使用StringBuilder和StringBuffer。

3、如果是通过一个List进行字符串拼接,则考虑使用StringJoiner。

以上就是本次介绍的全部知识点内容,感谢大家对脚本之家的支持。

相关文章

  • Spring rest接口中的LocalDateTime日期类型转时间戳

    Spring rest接口中的LocalDateTime日期类型转时间戳

    这篇文章主要介绍了Spring rest接口中的LocalDateTime日期类型转时间戳的方法,Java程序中一般将日期类型定义为LocalDateTime,数据库中保存的时间是0时区的时间
    2023-03-03
  • Spring框架中部署log4j.xml的详细步骤

    Spring框架中部署log4j.xml的详细步骤

    Log4j是一个常用的日志记录工具,它可以帮助我们记录应用程序的运行日志并进行灵活的配置,在Spring框架中,我们可以很方便地部署log4j.xml配置文件来管理日志记录,这篇文章主要介绍了Spring框架中部署log4j.xml的详细步骤并提供相应的代码示例,需要的朋友可以参考下
    2023-09-09
  • springboot解决java.lang.ArrayStoreException异常

    springboot解决java.lang.ArrayStoreException异常

    这篇文章介绍了springboot解决java.lang.ArrayStoreException异常的方法,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-12-12
  • spring mvc4的日期/数字格式化、枚举转换示例

    spring mvc4的日期/数字格式化、枚举转换示例

    本篇文章主要介绍了spring mvc4的日期/数字格式化、枚举转换示例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-01-01
  • mybatis一对多查询功能

    mybatis一对多查询功能

    这篇文章主要介绍了mybatis一对多查询功能,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2017-02-02
  • Java中类的加载器及其加载过程

    Java中类的加载器及其加载过程

    字节码文件在类加载器子系统中要进行加载、链接、初始化等处理,我们这里详细来谈其中过程,本文主要介绍了Java中类的加载器及其加载过程,感兴趣的同学可以参考一下
    2023-04-04
  • 一文梳理Java 8后的新功能

    一文梳理Java 8后的新功能

    Java 8是Java自Java 5(发布于2004年)之后的最重要的版本,下面这篇文章主要给大家介绍了关于Java8后新功能的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-02-02
  • Spring Boot使用JSR-380进行校验的示例

    Spring Boot使用JSR-380进行校验的示例

    这篇文章主要介绍了Spring Boot使用JSR-380进行校验,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • Java的Jackson库中复杂对象集合的几种简单转换

    Java的Jackson库中复杂对象集合的几种简单转换

    本文主要介绍了Java的Jackson库中复杂对象集合的几种简单转换。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • Spring Cloud微服务使用webSocket的方法

    Spring Cloud微服务使用webSocket的方法

    WebSocket在现代浏览器中的应用已经算是比较普遍了,在某些业务场景下,要求必须能够在服务器端推送消息至客户端,本文给大家介绍Spring Cloud微服务使用webSocket的方法,感兴趣的朋友一起看看吧
    2021-06-06

最新评论