Java1.8中StringJoiner的使用及源碼詳析
前言
StringJoiner是Java里1.8新增的類,主要是幫助我們把一個列表拼接字符串, 或許有一部分人沒有接觸過. 所以本文將從使用例子入手, 分析StringJoiner的源碼.
基本好的同學(xué), 其實只要把這段例子自己運行一下, 自己看看源碼就可以了.因為我覺得這個類挺簡單的. 沒必要看我下面的廢話....
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()); } }
輸出結(jié)果如下:
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
上面的例子看懂的同學(xué), 其實沒必要往下看下去了....下面的幾個例子就當(dāng)是我自己做了個總結(jié)吧.
例1
public class StringJoinerTest2 { public static void main(String[] args) { StringJoiner joiner = new StringJoiner("--", "[[[_ ", "_]]]"); System.out.println(joiner.toString()); System.out.println(joiner.length()); } }
輸出結(jié)果如下:
這個構(gòu)造器要傳入三個參數(shù). 第一個是`分隔符` , 第二個是`前綴` , 第三個是 `后綴`. 現(xiàn)在不明白也沒有關(guān)系, 下面待會兒會詳細介紹.
咱們先把這個構(gòu)造器對應(yīng)的源碼看了吧:
先是判斷非空. 然后就開始賦值了. emptyValue被賦值為了prefix+suffix . 這段代碼就是這么簡單... 其中:
1. prefix 是前綴. (待會兒再講)
2. delimiter 是分隔符 (待會兒再講)
3. suffix 是后綴 (待會兒再講)
4. emptyValue是本類的`空值`. 空值準確來說應(yīng)該是null, 但StringJoiner類把emptyValue來當(dāng)空值來處理. (馬上就講)
構(gòu)造器看完了, 咱們再看看toString方法:
因為目前的代碼里, 沒有對value進行過賦值操作, 所以value肯定是null. 所以會執(zhí)行第一個if.
也就是說真正的值value為空的時候, 就會返回本類默認的空值emptyValue. (大家有沒有現(xiàn)在應(yīng)該知道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()); } }
輸出結(jié)果如下:
這個時候, 或許大家對`前綴` `后綴` 有些理解了吧. (還沒理解也無所謂, 往下看)
咱們看看add方法的源碼吧:
通過append方法, 將咱們傳入的"1"添加到了末尾. 那么prepareBuilder()方法返回的是什么呢?看看源碼吧:
咱們調(diào)用add("1")的時候, value為空. 所以會執(zhí)行else語句. 在這里新實例化了一個StringBuilder. 然后StringBuilder先追加了`前綴`. (if語句先不講, 等執(zhí)行到了再講)
所以此時prepareBuilder方法返回的value實際上就是前綴: "[[[_"
回到add方法, 剛才咱們說了add方法即時在prepareBuilder返回的值后面追加了"1"而已.
所以執(zhí)行完add方法之后, value就等于 "[[[_1" 所以value里就已經(jīng)包含了前綴了. 所以length方法里"為什么不單獨再計算前綴的長度呢?" 因為value里面就已經(jīng)包含前綴了.
咱們再看看toString方法:
這次value非空. 所以執(zhí)行這里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()); } }
輸出結(jié)果如下:
add("1")和上一小節(jié)的執(zhí)行流程一樣. 這回看看add("2");的執(zhí)行流程吧:
由于前面add("1")執(zhí)行完了, 所以導(dǎo)致value已經(jīng)不是null了. 所以這里會執(zhí)行prepareBuilder方法里的if語句. 在value后直接追加一個delimiter分隔符. 然后返回這個value.
然后再add方法里, 把"2"追加到value后面.
例4
咱們發(fā)現(xiàn)add方法最后返回的是this.所以上面一小節(jié)的示例代碼可以寫成這樣:
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還有一個構(gòu)造器, 只需傳入分隔符:
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()); } }
輸出結(jié)果如下:
構(gòu)造器源碼如下:
就是只指定了分割符, 把前綴和后綴都指定為了空字符串.
例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()); } }
輸出結(jié)果如下:
merge的源代碼如下:
咱們看到了用append方法進行了字符串追加. (append的時候刨除去了other.value 的前綴).
總結(jié)
1. prepareBuilder方法在value為空的時候, 給value加上前綴.
2. prepareBuilder方法在value非空的時候, 給value加上分隔符.
3. 很多方法都不能傳入null為參數(shù). 因為用Objects.requireNonNul方法限定了.
4. 前綴是包含在value里的. 而后綴部分是toString的時候才會被臨時添加到value里.
好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關(guān)文章
基于Security實現(xiàn)OIDC單點登錄的詳細流程
本文主要是給大家介紹 OIDC 的核心概念以及如何通過對 Spring Security 的授權(quán)碼模式進行擴展來實現(xiàn) OIDC 的單點登錄。對Security實現(xiàn)OIDC單點登錄的詳細過程感興趣的朋友,一起看看吧2021-09-09Spring動態(tài)加載bean后調(diào)用實現(xiàn)方法解析
這篇文章主要介紹了Spring動態(tài)加載bean后調(diào)用實現(xiàn)方法解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-08-08Spring?Boot?快速使用?HikariCP?連接池配置詳解
Spring Boot 2.x 將其作為默認的連接池組件,項目中添加 spring-boot-starter-jdbc 或 spring-boot-starter-data-jpa 模塊后,HikariCP 依賴會被自動引入,這篇文章主要介紹了Spring?Boot使用HikariCP連接池配置詳解,需要的朋友可以參考下2023-06-06SpringBoot最常用的50個注解總結(jié)(全是干貨!)
SpringBoot提供多種注解簡化配置與啟動流程,如@SpringBootAppication、@RestController、@RequestMapping等,這篇文章主要介紹了SpringBoot最常用的50個注解的相關(guān)資料,需要的朋友可以參考下2024-09-09