概述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 个构造函数。构造函数很简单,没有什么可以多讲的,就是对 分隔符、前缀和后缀字符串的初始化。
public stringjoiner(charsequence delimiter) { this(delimiter, , ); } public stringjoiner(charsequence delimiter, charsequence prefix, charsequence suffix) { objects.requirenonnull(prefix, the prefix must not be null); objects.requirenonnull(delimiter, the delimiter must not be null); objects.requirenonnull(suffix, the suffix must not be null); // make defensive copies of arguments this.prefix = prefix.tostring(); this.delimiter = delimiter.tostring(); this.suffix = suffix.tostring(); }另外 stringjoiner 有 5 个公有方法,其中比较常用的就是 add 和 tostring 。我们也来看看这两个常用方法。
public final class stringjoiner { private string[] elts; @override public string tostring() { final string[] elts = this.elts; if (elts == null && emptyvalue != null) { return emptyvalue; } final int size = this.size; final int addlen = prefix.length() + suffix.length(); if (addlen == 0) { compactelts(); return size == 0 ? : elts[0]; } final string delimiter = this.delimiter; final char[] chars = new char[len + addlen]; int k = getchars(prefix, chars, 0); if (size > 0) { k += getchars(elts[0], chars, k); for (int i = 1; i < size; i++) { k += getchars(delimiter, chars, k); k += getchars(elts[i], chars, k); } } k += getchars(suffix, chars, k); return new string(chars); } public stringjoiner add(charsequence newelement) { final string elt = string.valueof(newelement); if (elts == null) { elts = new string[8]; } else { if (size == elts.length) elts = arrays.copyof(elts, 2 * size); len += delimiter.length(); } len += elt.length(); elts[size++] = elt; return this; }}我们来看下 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).
* @see java.util.stream.collectors#joining(charsequence) * @see java.util.stream.collectors#joining(charsequence, charsequence, charsequence)那我们就顺藤摸瓜,看看 collectors#joining 有什么跟 stringjoiner 有关联的呢?
public static collector joining() { return new collectorimpl( stringbuilder::new, stringbuilder::append, (r1, r2) - > { r1.append(r2); return r1; }, stringbuilder::tostring, ch_noid); } public static collector joining(charsequence delimiter) { return joining(delimiter, , ); } public static collector joining(charsequence delimiter, charsequence prefix, charsequence suffix) { return new collectorimpl( () - > new stringjoiner(delimiter, prefix, suffix), stringjoiner::add, stringjoiner::merge, stringjoiner::tostring, ch_noid); }原来啊,java 8 中 stream 是借助了 stringjoiner 来实现的。这个时候,我们可能会想,为什么不使用 stringbuilder 来实现呢?我们可以从上面的代码里看出,如果 使用 stringbuilder 来构造拼接的话,在没有前后缀的情况下,应该还是简单的,事实上jdk 官方组织也选择了 stringbuilder 。但是一旦涉及到拼接之类的操作,那如果还是使用 stringbuilder 的话,那就真的是太复杂了。
所以 stringjoiner 在 java 8 的地位是 stringbuilder 所不能代替的。
总结本文介绍了 java 8 开始提供的字符串拼接类 stringjoiner。jdk 8 中 stringjoiner 是通过 stringbuilder 实现的, 所以它的性能和 stringbuilder 差不多,它也是非线程安全的。jdk 11 中已经对其进行了优化,通过 string[] 来代理 stringbuilder 。
在日常的开发过程中,我们怎么选择字符串拼接类呢?
简单的字符串拼接,直接使用 + 即可。在 for 循环之类的场景下需要字符串拼接,可以优先考虑使用 stringbuilder 。在使用 java stream 的场景下需要字符串拼接,可以优先考虑使用 stringjoiner。
渠道变革?传小鹏汽车销售区域缩减一半
大屏来袭:6.0寸超大屏三星Galaxy S8 plus 或将取消home等物理按键?
激光焊接机价格是多少钱一台
LoRa芯片规格参数、内部架构及参考设计详解
蔚来的大手笔投入门店设计,究竟是作局还是做事呢?
Java 8新增的 StringJoiner用法
福禄克全新发布Fluke 930转速计
福尔哈贝可消毒2057…BA系列电机,转速最高可达65,000 rpm
python while循环详解
OPPO在专利诉讼中获胜的原因
老鼠爱大米的乐谱到24c02中(源程序)
华为Nova 8:搭载麒麟985芯片
华为全面升级CloudFabric 3.0数据中心网络解决方案
利用智能PLC压铸模温机提高5G基站产品的生产效率
跨境电商独立站太烧钱?中小企业老板快收藏华为云这份省钱秘笈
华虹NEC开发出嵌入式非挥发性存储器模块(EEPROM/FlashIP)
真菌毒素快速检测设备产品介绍
微软New Surface Pro多少钱?Surface Pro 2017全系价格一览
基于RFID的拉式生产是怎么回事
未来智能穿戴产品的发展方向