>>分享Java编程技术,对《Java面向对象编程》等书籍提供技术支持 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 29289 个阅读者 刷新本主题
 * 贴子主题:  用JDK中的StringJoiner进行字符串拼接 回复文章 点赞(0)  收藏  
作者:flybird    发表时间:2019-03-16 00:26:44     消息  查看  搜索  好友  邮件  复制  引用


介绍

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("HelloA,");

        sj.add("HelloB,");
        sj.add("HelloC");
        System.out.println(sj.toString());

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

        sj1.add("HelloA").add("HelloB").add("HelloC");
        System.out.println(sj1.toString());
    }
}

以上代码输出结果:
HelloA,HelloB,HelloC
[HelloA:HelloB:HelloC]

值得注意的是,当我们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。







程序猿的技术大观园:www.javathinker.net
  Java面向对象编程-->类的生命周期
  JavaWeb开发-->开发JavaMail Web应用
  JSP与Hibernate开发-->立即检索和延迟检索策略
  Java网络编程-->对象的序列化与反序列化
  精通Spring-->
  Vue3开发-->通过Vuex进行状态管理
  实用类 EncodingDetect,查看一个文件的字符编码
  序列化与反序列化知识点汇总
  面试官:NIO的优化实现原理了解吗?图文结合教你如何正确避坑
  深入Java单例模式
  Java Optional 解决空指针异常总结
  靠一个HashMap的讲解打动了头条面试官
  好消息:孙卫琴老师等直播分享Java分布式架构专题
  java NIO示例以及流程详解
  Synchronized与ReentrantLock区别总结
  JNI_Java Native Interface的用法
  Eclipse使用指南:Debug 配置
  Java设计模式:观察者模式
  Socket服务器的整体架构
  正则表达式性能调优
  Java入门实用代码:修改链表LinkedList
  更多...
 IPIP: 已设置保密
楼主      
1页 0条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


中文版权所有: JavaThinker技术网站 Copyright 2016-2026 沪ICP备16029593号-2
荟萃Java程序员智慧的结晶,分享交流Java前沿技术。  联系我们
如有技术文章涉及侵权,请与本站管理员联系。