[源碼分析]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里.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM