zoukankan      html  css  js  c++  java
  • [源码分析]Java1.8中StringJoiner的使用以及源码分析

    [源码分析]StringJoiner的使用以及源码分析

    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里.

  • 相关阅读:
    升级windows 11小工具
    windows 10更新升级方法
    您需要了解的有关 Oracle 数据库修补的所有信息
    Step by Step Apply Rolling PSU Patch In Oracle Database 12c RAC Environment
    Upgrade Oracle Database Manually from 12.2.0.1 to 19c
    如何应用版本更新 12.2.0.1.210420(补丁 32507738 – 2021 年 4 月 RU)
    xtrabackup 安装、备份和恢复
    Centos_Lvm expand capacity without restarting CentOS
    Centos_Lvm_Create pv vg lv and mount
    通过全备+relaylog同步恢复被drop的库或表
  • 原文地址:https://www.cnblogs.com/noKing/p/java_source_StringJoiner.html
Copyright © 2011-2022 走看看