拼接字符串,还能这么玩

简介: 大家好,我是指北君。

前言


最近呢,指北君的朋友小王在面试的时候,又遇到了问题,再次回家等通知,找个工作不容易啊,太卷了。

面试官:你知道使用原生 JDK 拼接字符串有多少种玩法吗?

小王StringBuilderStringBufferString.concat、还有用 + 拼接。(这也太简单了吧,小王心理OS。)

面试官又问,还有其他的方法吗?

小王有点开始纳闷了,还有其他的吗?没见过呀。难道是字符数组来拼接出来。

小王:字符数组拼接。

面试官还是继续追问,还有吗?小王心想还能有啥啊,该说的我都说了啊,更多的我也不知道啦,只能回答没有了。

面试官见状提醒了小王,你在用JDK 1.8及以上版本吗?Java 8 里面新增了一个拼接字符串的类 ,叫 StringJoiner ,你可以去看一下。小王很无奈,这个类还真没看到过。

小王面完找指北君来诉苦,指北君马上安排一篇文章,发给了小王。

接下来呢,指北君就要带大家来了解一下这个 Java 8 开始新增的 StringJoiner 的用法。


概述


StringJoiner is used to construct a sequence of characters separated by a delimiter and optionally starting with a supplied prefix and ending with a supplied suffix.

Prior to adding something to the StringJoiner, its sj.toString() method will, by default, return prefix + suffix. However, if the setEmptyValue method is called, the emptyValue supplied will be returned instead. This can be used, for example, when creating a string using set notation to indicate an empty set, i.e. "{}", where the prefix is "{", the suffix is "}" and nothing has been added to the StringJoiner.

StringJoiner 源码的定义可以看出,它是 java.util 包中的一个类,被用来构造一个由分隔符分隔的字符串,并且可以从提供的前缀字符串开头,以提供的后缀字符串结尾。

通常我们拼接字符串都是使用 StringBuilder 或者 StringBuffer 来实现的。这个时候,我们可能就会有一个疑问了, StringJoiner 的价值是什么?到底为什么要到这个时候创造它。


源码解析


好,我们先看一下 StringJoiner 的构造函数, StringJoiner 一共有 2 个构造函数。构造函数很简单,没有什么可以多讲的,就是对 分隔符、前缀和后缀字符串的初始化。

50.png

另外 StringJoiner 有 5 个公有方法,其中比较常用的就是 addtoString 。我们也来看看这两个常用方法。


51.png52.png


我们来看下 add 方法的实现,看起来也挺简单的,就是把待拼接的字符串,放到一个字符串数组里面。toString() 方法的时候,才是真正做字符串拼接的过程。我例子中的代码是 JDK 11, 相比 JDK 8 中,StringJoiner 是通过 StringBuilder 来实现的。

既然 JDK 8 的时候,已经使用了StringBuilder 来实现,那么为什么还要改成 String[]  来缓存所有的待拼接的字符串。这个就要涉及到JVM底层的优化,我们这里暂时不展开讲这个问题了。

前面已经提过既然已经有了 StringBuilder,为什么还要造一个StringJoiner,它的优势到底在哪里,我们接着来找找原因。很快我们在代码类的注释中找到了猫腻,在注释中标记了Collectors#joining

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

52.png53.png

那我们就顺藤摸瓜,看看 Collectors#joining 有什么跟 StringJoiner 有关联的呢?

54.png


原来啊,Java 8Stream 是借助了 StringJoiner 来实现的。这个时候,我们可能会想,为什么不使用 StringBuilder 来实现呢?我们可以从上面的代码里看出,如果 使用 StringBuilder 来构造拼接的话,在没有前后缀的情况下,应该还是简单的,事实上JDK 官方组织也选择了 StringBuilder 。但是一旦涉及到拼接之类的操作,那如果还是使用 StringBuilder 的话,那就真的是太复杂了。

所以 StringJoinerJava 8 的地位是 StringBuilder 所不能代替的。


总结


本文介绍了 Java 8 开始提供的字符串拼接类 StringJoinerJDK 8StringJoiner 是通过 StringBuilder 实现的, 所以它的性能和 StringBuilder 差不多,它也是非线程安全的。JDK 11 中已经对其进行了优化,通过 String[] 来代理 StringBuilder

在日常的开发过程中,我们怎么选择字符串拼接类呢?

  1. 简单的字符串拼接,直接使用 + 即可。
  2. 在 for 循环之类的场景下需要字符串拼接,可以优先考虑使用 StringBuilder 。
  3. 在使用 Java Stream 的场景下需要字符串拼接,可以优先考虑使用 StringJoiner。

有任何问题可以在公众号后台留言,指北君会第一时间回复大家。欢迎关注公众号【Java技术指北】,第一时间获取更多精彩内容。

相关文章
|
6月前
|
C语言
字符串连接
字符串连接
|
6月前
|
存储 安全 算法
做50个Java字符串题即精通字符串
字符串常量池是 Java 堆内存的一个特殊存储区域,用于存储字符串字面量和字符串常量。Java 虚拟机为了节省内存空间和提高效率,会确保所有的字符串字面量只包含一份,这样如果有多个引用指向相同的字面量,它们实际上会指向内存中相同的位置。字符串不可变性意味着一旦字符串对象被创建,它所包含的字符序列就不能被更改。Java 中的String对象是不可变的,因为不可变性可以提供编译时的优化、线程安全性,以及因为字符串常量池而更好的内存效率。
122 0
两种字符串替换的方法
两种字符串替换的方法
88 0
|
索引
分割字符串的方法
分割字符串的方法
100 0
字符串截取
字符串截取
60 0
|
人工智能 C#
C# 字符串拼接
除了可以通过加号来拼接字符串之外,我们还可以使用格式化字符串的方法来拼接字符串。中,字符串没有相加的数学运算,但它可以通过加号。是唯一可以用于字符串运算的算数运算符,别的。这样也可以实现字符串的拼接。也可以和复合赋值运算符。
140 0
C# 字符串拼接
|
SQL Java
拼接字符串?试试 StringJoiner
我们通常需要拼接字符串的时候呢,多半都是使用 StringBuffer 或 StingBuilder 进行循环遍历拼接,这样既费时又费力,本次推荐 Java8 中推出的 StringJoiner
102 0
|
C++
C++常用字符串分割方法
来源:http://www.jb51.net/article/55954.htm 一、用strtok函数进行字符串分割 原型: char *strtok(char *str, const char *delim); 功能:分解字符串为一组字符串。 参数说明:str为要分解的字符串,delim为分隔符字符串。 返回值:从str开头开始的一个个被分
6575 0
【Groovy】字符串 ( 字符串拼接 | 多行字符串 )
【Groovy】字符串 ( 字符串拼接 | 多行字符串 )
499 0
【Groovy】字符串 ( 字符串拼接 | 多行字符串 )