Java1.8中StringJoiner的使用及源码详析
作者:GoldArowana 发布时间:2021-09-09 14:37:32
前言
StringJoiner是Java里1.8新增的类,主要是帮助我们把一个列表拼接字符串, 或许有一部分人没有接触过. 所以本文将从使用例子入手, 分析StringJoiner的源码.
基本好的同学, 其实只要把这段例子自己运行一下, 自己看看源码就可以了.因为我觉得这个类挺简单的. 没必要看我下面的废话....
public class StringJoinerTest {
public static void main(String[] args) {
StringJoiner joiner = new StringJoiner("--", "[[[_", "_]]]");
System.out.println("toString: " + joiner.toString());
System.out.println("length: " + joiner.length());
System.out.println("******************(1)********************");
joiner.add("1");
joiner.add("2");
joiner.add("3");
joiner.add("4");
System.out.println("toString: " + joiner.toString());
System.out.println("length: " + joiner.length());
System.out.println("******************(2)********************");
StringJoiner joiner2 = new StringJoiner("...");
System.out.println("toString: " + joiner2.toString());
System.out.println("length: " + joiner2.length());
System.out.println("******************(3)********************");
joiner2.add("a");
joiner2.add("b");
joiner2.add("c");
System.out.println("toString: " + joiner2.toString());
System.out.println("length: " + joiner2.length());
System.out.println("******************(4)********************");
joiner.merge(joiner2);
System.out.println("toString: " + joiner.toString());
System.out.println("******************(5)********************");
StringJoiner joiner3 = new StringJoiner("==", "qianzhui", "houzhui");
joiner3.add("壹");
joiner3.add("贰");
joiner3.add("叁");
joiner.merge(joiner3);
System.out.println("toString: " + joiner.toString());
System.out.println("length: " + joiner.length());
System.out.println("******************(6)********************");
joiner.merge(joiner); // joiner.merge(this)
System.out.println("toString: " + joiner.toString());
System.out.println("length: " + joiner.length());
}
}
输出结果如下:
toString: [[[__]]]
length: 8
******************(1)********************
toString: [[[_1--2--3--4_]]]
length: 18
******************(2)********************
toString:
length: 0
******************(3)********************
toString: a...b...c
length: 9
******************(4)********************
toString: [[[_1--2--3--4--a...b...c_]]]
******************(5)********************
toString: [[[_1--2--3--4--a...b...c--壹==贰==叁_]]]
length: 38
******************(6)********************
toString: [[[_1--2--3--4--a...b...c--壹==贰==叁--1--2--3--4--a...b...c--壹==贰==叁_]]]
length: 70
上面的例子看懂的同学, 其实没必要往下看下去了....下面的几个例子就当是我自己做了个总结吧.
例1
public class StringJoinerTest2 {
public static void main(String[] args) {
StringJoiner joiner = new StringJoiner("--", "[[[_ ", "_]]]");
System.out.println(joiner.toString());
System.out.println(joiner.length());
}
}
输出结果如下:
这个构造器要传入三个参数. 第一个是`分隔符` , 第二个是`前缀` , 第三个是 `后缀`. 现在不明白也没有关系, 下面待会儿会详细介绍.
咱们先把这个构造器对应的源码看了吧:
先是判断非空. 然后就开始赋值了. emptyValue被赋值为了prefix+suffix . 这段代码就是这么简单... 其中:
1. prefix 是前缀. (待会儿再讲)
2. delimiter 是分隔符 (待会儿再讲)
3. suffix 是后缀 (待会儿再讲)
4. emptyValue是本类的`空值`. 空值准确来说应该是null, 但StringJoiner类把emptyValue来当空值来处理. (马上就讲)
构造器看完了, 咱们再看看toString方法:
因为目前的代码里, 没有对value进行过赋值操作, 所以value肯定是null. 所以会执行第一个if.
也就是说真正的值value为空的时候, 就会返回本类默认的空值emptyValue. (大家有没有现在应该知道emptyValue的作用了吧)
toString就先分析这一小段if, 剩下的后面再讲. 接下来咱们看看length()方法:
value非空的时候, 长度就是value的长度+后缀的长度.(前缀呢? 前缀去哪儿了? 为什么不单独再加上前缀的长度呢? 带着这个疑惑往下看) .
value为空的时候, 长度就是emptyValue的长度.
例2
咱们往StringJoiner添加"1"
public class StringJoinerTest2 {
public static void main(String[] args) {
StringJoiner joiner = new StringJoiner("--", "[[[_", "_]]]");
joiner.add("1");
System.out.println("toString: " + joiner.toString());
System.out.println("length: " + joiner.length());
}
}
输出结果如下:
这个时候, 或许大家对`前缀` `后缀` 有些理解了吧. (还没理解也无所谓, 往下看)
咱们看看add方法的源码吧:
通过append方法, 将咱们传入的"1"添加到了末尾. 那么prepareBuilder()方法返回的是什么呢?看看源码吧:
咱们调用add("1")的时候, value为空. 所以会执行else语句. 在这里新实例化了一个StringBuilder. 然后StringBuilder先追加了`前缀`. (if语句先不讲, 等执行到了再讲)
所以此时prepareBuilder方法返回的value实际上就是前缀: "[[[_"
回到add方法, 刚才咱们说了add方法即时在prepareBuilder返回的值后面追加了"1"而已.
所以执行完add方法之后, value就等于 "[[[_1" 所以value里就已经包含了前缀了. 所以length方法里"为什么不单独再计算前缀的长度呢?" 因为value里面就已经包含前缀了.
咱们再看看toString方法:
这次value非空. 所以执行这里else语句:
如果suffix等于空字符串, 那么就返回value.
如果suffix不等于空字符串, 那么就返回value+后缀.
再看看length()方法:
value不为空, 所以返回的值是 value的长度+后缀的长度.
例3
public class StringJoinerTest2 {
public static void main(String[] args) {
StringJoiner joiner = new StringJoiner("--", "[[[_", "_]]]");
joiner.add("1");
joiner.add("2");
joiner.add("3");
joiner.add("4");
System.out.println("toString: " + joiner.toString());
System.out.println("length: " + joiner.length());
}
}
输出结果如下:
add("1")和上一小节的执行流程一样. 这回看看add("2");的执行流程吧:
由于前面add("1")执行完了, 所以导致value已经不是null了. 所以这里会执行prepareBuilder方法里的if语句. 在value后直接追加一个delimiter分隔符. 然后返回这个value.
然后再add方法里, 把"2"追加到value后面.
例4
咱们发现add方法最后返回的是this.所以上面一小节的示例代码可以写成这样:
public class StringJoinerTest2 {
public static void main(String[] args) {
StringJoiner joiner = new StringJoiner("--", "[[[_", "_]]]");
joiner.add("1").add("2").add("3").add("4");
System.out.println("toString: " + joiner.toString());
System.out.println("length: " + joiner.length());
}
}
例5
StringJoiner还有一个构造器, 只需传入分隔符:
public class StringJoinerTest2 {
public static void main(String[] args) {
StringJoiner joiner2 = new StringJoiner("...");
System.out.println("toString: " + joiner2.toString());
System.out.println("length: " + joiner2.length());
System.out.println("**************************************");
joiner2.add("a");
joiner2.add("b");
joiner2.add("c");
System.out.println("toString: " + joiner2.toString());
System.out.println("length: " + joiner2.length());
}
}
输出结果如下:
构造器源码如下:
就是只指定了分割符, 把前缀和后缀都指定为了空字符串.
例6
接下来咱们看看merge方法
public class StringJoinerTest2 {
public static void main(String[] args) {
StringJoiner joiner = new StringJoiner("--", "[[[_", "_]]]");
joiner.add("1").add("2").add("3").add("4");
StringJoiner joiner2 = new StringJoiner("...");
joiner2.add("a").add("b").add("c");
joiner.merge(joiner2);
System.out.println(joiner.toString());
}
}
输出结果如下:
merge的源代码如下:
咱们看到了用append方法进行了字符串追加. (append的时候刨除去了other.value 的前缀).
总结
1. prepareBuilder方法在value为空的时候, 给value加上前缀.
2. prepareBuilder方法在value非空的时候, 给value加上分隔符.
3. 很多方法都不能传入null为参数. 因为用Objects.requireNonNul方法限定了.
4. 前缀是包含在value里的. 而后缀部分是toString的时候才会被临时添加到value里.
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。
来源:http://www.cnblogs.com/noKing/p/java_source_StringJoiner.html


猜你喜欢
- C++String类型的逆序这里使用反向迭代器实现#include<iostream> #include <string&
- 说明:在阅读本篇文章之前建议大家先详细学习一下spring的相关知识,有助于更深刻的理解spirngboot的配置原理。一、什么是sprin
- 1. JAVA源文件的命名JAVA源文件名必须和源文件中所定义的类的类名相同。2. Package的命名Package名的第一部分应是小写A
- 本文实例讲述了Android控件之Gallery用法。分享给大家供大家参考。具体如下:Gallery组件主要用于横向显示图像列表,不过按常规
- 本文实例讲述了C#创建、读取和修改Excel的方法。分享给大家供大家参考。具体如下:windows下我们可以通过 Jet OLE DB访问E
- 搭建测试的数据库和表数据的SQL/* Navicat Premium Data TransferSource Server &
- C# WinForm控件的拖动和缩放是个很有用的功能。实现起来其实很简单的,主要是设计控件的MouseDown、MouseLeave、Mou
- 今天在网上看到了一个关于读取网络文件的小视频,觉得不错,拿来与大家分享思路具体的思路比较的简单,但是思想非常的单纯。那就是输入一个网址,点击
- 本文实例讲述了Spring实战之属性占位符配置器用法。分享给大家供大家参考,具体如下:一 配置文件<?xml version=&quo
- Looper是整个跨线程通信的管理者 // 内部持有的变量如下: ThreadLocal
- 简介这篇文章我一直在纠结到底要不要写,不想写一来因为定时器用法比较简单,二来是面试中也不常问。后来还是决定写了主要是想把自己分析问题思路分享
- Java是一种强类型, 许多流行的编程语言都已经支持局部变量类型推断,如js,Python,C++等JDK10 可以使用var作为局部变量类
- 在派生类中引发基类事件以下简单示例演示了在基类中声明可从派生类引发的事件的标准方法。此模式广泛应用于 .NET Framework 类库中的
- 组合模式及其在JDK源码中的运用 前言组合和聚合什么是组合模式示例透明组合模式透明组合模式的缺陷安全组合模式 组合模式角色组合模式在JDK源
- 背景笔者使用 Spring Security 5.8 时,发现网上很多教程所教的 Spring Security 配置类 SecurityC
- 实现闹钟运行的效果如下: 通知栏的运行后效果图如下:布局文件(activity_main.xml)<?xml version
- Android listview的滑动冲突解决方法在Android开发的过程中,有时候会遇到子控件和父控件都要滑动的情况,尤其是当子控件为l
- 在很多系统开发中,我们希望在指定的方法调用之前或者之后能打印出该方法的调用时间以及方法的出参和入参,就可以使用spring的AOP,还可以结
- Warning:这是《Java 程序员进阶之路》专栏的第 55 篇。回来后小二找到了我,于是我就写下了这篇文章丢给他,并严厉地告诉他:再搞不
- 本篇分析ArrayList的源码,在分析之前先跟大家谈一谈数组。数组可能是我们最早接触到的数据结构之一,它是在内存中划分出一块连续的地址空间