java實(shí)戰(zhàn)小技巧之優(yōu)雅的實(shí)現(xiàn)字符串拼接
前言
字符串拼接不管是在業(yè)務(wù)上,還是寫(xiě)算法時(shí)都會(huì)頻繁使用到。
相信沒(méi)有小伙伴沒(méi)有寫(xiě)過(guò)這樣的代碼,比如說(shuō)現(xiàn)在讓我們來(lái)實(shí)現(xiàn)一個(gè)字符串拼接的場(chǎng)景,怎樣的實(shí)現(xiàn)才算是優(yōu)雅的呢?
以將int數(shù)組轉(zhuǎn)為英文逗號(hào)分隔的字符串為例進(jìn)行演示
String底層原理
在討論字符串拼接時(shí),首先需要知道String的底層原理。
看下結(jié)構(gòu)
private final byte[] value;
這一行代碼已經(jīng)可以說(shuō)明很多東西。字符串實(shí)質(zhì)就是不可變的byte數(shù)組。因?yàn)椴豢勺儯詫?duì)他進(jìn)行拼接對(duì)他拼接實(shí)際就是生成了多個(gè)對(duì)象,這就是不鼓勵(lì)對(duì)字符串進(jìn)行拼接的原因。但不可變也有很多好處,例如線(xiàn)程安全、可以存在字符串緩沖池復(fù)用字符串等。
1. 普通寫(xiě)法
直接使用StringBuilder來(lái)拼接
public String join(List<Integer> list) { StringBuilder builder = new StringBuilder(); for(Integer sub: list) { builder.append(sub).append(","); } return builder.substring(0, builder.length() - 1); }
上面這種寫(xiě)法相信比較常見(jiàn),相對(duì)來(lái)說(shuō)不太順眼的地方就是最后的toString,需要將最后的一個(gè)英文逗號(hào)給干掉
當(dāng)然也可以用下面這種事前判斷方式,避免最終的字符串截取
public String join2(List<Integer> list) { StringBuilder builder = new StringBuilder(); boolean first = true; for (Integer sub: list) { if (first) { first = false; } else { builder.append(","); } builder.append(sub); } return builder.toString(); }
2. StringJoiner
上面實(shí)現(xiàn)中,干掉最后的一個(gè)分隔符實(shí)在不是很優(yōu)雅,那么有更好一點(diǎn)的用法么,接下來(lái)看一下使用StringJoiner的方式
public String join3(List<Integer> list) { StringJoiner joiner = new StringJoiner(","); for (Integer s : list) { joiner.add(String.valueOf(s)); } return joiner.toString(); }
StringJoiner由jdk1.8提供,除了上面的基礎(chǔ)玩法之外,結(jié)合jdk1.8帶來(lái)的流操作方式,可以更簡(jiǎn)潔的實(shí)現(xiàn)
return list.stream().map(String::valueOf).collect(Collectors.joining(","));
怎么樣,上面這個(gè)實(shí)現(xiàn)比起前面的代碼是不是要簡(jiǎn)潔多了,一行代碼完事
3. guava joiner
如果使用的jdk還不是1.8版本,不能使用上面的StringJoiner,沒(méi)關(guān)系,還有g(shù)uava的Joiner也可以實(shí)現(xiàn)
public String join5(List<Integer> list) { return Joiner.on(",").join(list); }
注意
接收的參數(shù)類(lèi)型為: 數(shù)組/Iterable/Iterator/可變參數(shù), 基本上可以覆蓋我們?nèi)粘5臉I(yè)務(wù)場(chǎng)景
4. 小結(jié)
本篇文章的主題是一個(gè)非常非常常見(jiàn)的字符串拼接,一般來(lái)講,我們?cè)谧鲎址唇訒r(shí),最麻煩的事情就是分隔符的處理,要么就是分隔符前置添加,每次循環(huán)都需要判斷是否為開(kāi)頭;要么就是后置,最后取字符串時(shí),干掉最后一個(gè)分隔符
本文提供了一個(gè)非常使用的方式StringJoiner,完全解決了上面的分隔符問(wèn)題,它的使用有兩種場(chǎng)景
- 簡(jiǎn)單的容器轉(zhuǎn)String:直接借助Stream的Collectors.joining來(lái)實(shí)現(xiàn)
- for循環(huán) (這種場(chǎng)景一般是for循環(huán)內(nèi)的邏輯不僅僅包括字符串拼接,還包括其他的業(yè)務(wù)邏輯): 循環(huán)內(nèi)直接執(zhí)行stringJoiner.add()添加
對(duì)于jdk1.8及以上的版本,優(yōu)先推薦使用上面說(shuō)的StringJoiner來(lái)實(shí)現(xiàn)
總結(jié)
到此這篇關(guān)于java實(shí)戰(zhàn)小技巧之優(yōu)雅實(shí)現(xiàn)字符串拼接的文章就介紹到這了,更多相關(guān)java字符串拼接內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java 的 FileFilter文件過(guò)濾與readline讀行操作實(shí)例代碼
這篇文章介紹了Java 的 FileFilter文件過(guò)濾與readline讀行操作實(shí)例代碼,有需要的朋友可以參考一下2013-09-09Java線(xiàn)程池運(yùn)行狀態(tài)監(jiān)控實(shí)現(xiàn)解析
這篇文章主要介紹了Java線(xiàn)程池運(yùn)行狀態(tài)監(jiān)控實(shí)現(xiàn)解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10Java網(wǎng)絡(luò)編程中的TCP/UDP詳解
這篇文章主要介紹了Java網(wǎng)絡(luò)編程中的TCP/UDP詳解,網(wǎng)絡(luò)編程是指編寫(xiě)運(yùn)行在多個(gè)設(shè)備的程序,這些設(shè)備都通過(guò)網(wǎng)絡(luò)連接起來(lái),java.net 包中 J2SE 的 API 包含有類(lèi)和接口,它們提供低層次的通信細(xì)節(jié),需要的朋友可以參考下2023-12-12springboot?整合表達(dá)式計(jì)算引擎?Aviator?使用示例詳解
本文詳細(xì)介紹了Google?Aviator?這款高性能、輕量級(jí)的?Java?表達(dá)式求值引擎,并通過(guò)詳細(xì)的代碼操作演示了相關(guān)API的使用以及如何在springboot項(xiàng)目中進(jìn)行集成,感興趣的朋友一起看看吧2024-08-08Java中Scanner類(lèi)與BufferReader類(lèi)的不同點(diǎn)(非常詳細(xì))
這篇文章主要介紹了Java中Scanner類(lèi)與BufferReader類(lèi)的不同點(diǎn)(非常詳細(xì))的相關(guān)資料,需要的朋友可以參考下2016-08-08JAVA如何把數(shù)據(jù)庫(kù)的數(shù)據(jù)處理成樹(shù)形結(jié)構(gòu)
本文介紹了JAVA如何把數(shù)據(jù)庫(kù)的數(shù)據(jù)處理成樹(shù)形結(jié)構(gòu),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09Mybatis中通過(guò)generator生成mapper、Dao、mapper.xml的方法
這篇文章主要介紹了Mybatis中通過(guò)generator生成mapper、Dao、mapper.xml的方法,需要的朋友可以參考下2017-01-01