歡迎光臨
每天分享高質量文章

字串拼接新姿勢:StringJoiner

來自:Hollis(微訊號:hollischuang)

 

為什麼阿裡巴巴不建議在for迴圈中使用”+”進行字串拼接一文中,我們介紹了幾種Java中字串拼接的方式,以及優缺點。其中還有一個重要的拼接方式我沒有介紹,那就是Java 8中提供的StringJoiner ,本文就來介紹一下這個字串拼接的新兵。

如果你想知道一共有多少種方法可以進行字串拼接,教你一個簡單的辦法,在Intellij IDEA中,定義一個Java Bean,然後嘗試使用快捷鍵自動生成一個toString方法,IDEA會提示多種toString生成策略可供選擇。

目前我使用的IDEA的toString生成策略預設的是使用JDK 1.8提供的StringJoiner。

1

介紹

StringJoiner是java.util包中的一個類,用於構造一個由分隔符分隔的字元序列(可選),並且可以從提供的字首開始並以提供的字尾結尾。

雖然這也可以在StringBuilder類的幫助下在每個字串之後附加分隔符,但StringJoiner提供了簡單的方法來實現,而無需編寫大量程式碼。

StringJoiner類共有2個建構式,5個公有方法。其中最常用的方法就是add方法和toString方法,類似於StringBuilder中的append方法和toString方法。

2

用法

StringJoiner的用法比較簡單,下麵的程式碼中,我們使用StringJoiner進行了字串拼接。

public class StringJoinerTest {

    public static void main(String[] args{
        StringJoiner sj = new StringJoiner(“Hollis”);

        sj.add(“hollischuang”);
        sj.add(“Java乾貨”);
        System.out.println(sj.toString());

        StringJoiner sj1 = new StringJoiner(“:”,“[“,“]”);

        sj1.add(“Hollis”).add(“hollischuang”).add(“Java乾貨”);
        System.out.println(sj1.toString());
    }
}


以上程式碼輸出結果:

hollischuangHollisJava乾貨
[Hollis:hollischuang:Java乾貨]


值得註意的是,當我們使用StringJoiner(CharSequence delimiter)初始化一個StringJoiner的時候,這個delimiter其實是分隔符,並不是可變字串的初始值

StringJoiner(CharSequence delimiter,CharSequence prefix,CharSequence suffix)的第二個和第三個引數分別是拼接後的字串的字首和字尾。

3

原理

介紹了簡單的用法之後,我們再來看看這個StringJoiner的原理,看看他到底是如何實現的。主要看一下add方法:

public StringJoiner add(CharSequence newElement{
prepareBuilder().append(newElement);
return this;
}

private StringBuilder prepareBuilder() {
if (value != null) {
value.append(delimiter);
else {
value = new StringBuilder().append(prefix);
}
return value;
}


看到了一個熟悉的身影——StringBuilder ,沒錯,StringJoiner其實就是依賴StringBuilder實現的為什麼阿裡巴巴不建議在for迴圈中使用”+”進行字串拼接中我們介紹過StringBuilder的實現原理,本文不在贅述。

當我們發現StringJoiner其實是透過StringBuilder實現之後,我們大概就可以猜到,StringJoiner效能損耗應該和直接使用StringBuilder差不多

為什麼需要StringJoiner

在了解了StringJoiner的用法和原理後,可能很多讀者就會產生一個疑問,明明已經有一個StringBuilder了,為什麼Java 8中還要定義一個StringJoiner呢?到底有什麼好處呢?

如果讀者足夠瞭解Java 8的話,或許可以猜出個大概,這肯定和Stream有關。

作者也在Java doc中找到了答案:

A StringJoiner may be employed to create formatted output from a Stream using Collectors.joining(CharSequence)

試想,在Java中,如果我們有這樣一個List:

List list = ImmutableList.of(“Hollis”,“hollischuang”,“Java乾貨”);


如果我們想要把他拼接成一個以下形式的字串:

Hollis,hollischuang,Java乾貨


可以透過以下方式:

StringBuilder builder = new StringBuilder();

if (!list.isEmpty()) {
builder.append(list.get(0));
for (int i = 1, n = list.size(); i         builder.append(“,”).append(list.get(i));
}
}
builder.toString();


還可以使用:

list.stream().reduce(new StringBuilder(), (sb, s) -> sb.append(s).append(‘,’), StringBuilder::append).toString();


但是輸出結果稍有些不同,需要進行二次處理:

Hollis,hollischuang,Java乾貨,


還可以使用”+”進行拼接:

list.stream().reduce((a,b)->a + “,” + b).toString();


以上幾種方式,要麼是程式碼複雜,要麼是效能不高,或者無法直接得到想要的結果。

為了滿足類似這樣的需求,Java 8中提供的StringJoiner就派上用場了。以上需求只需要一行程式碼:

list.stream().collect(Collectors.joining(“:”))


即可。上面用的運算式中,Collector.joining的源程式碼如下:

public static Collector joining(CharSequence delimiter,CharSequence prefix,CharSequence suffix) {
return new CollectorImpl<>(
() -> new StringJoiner(delimiter, prefix, suffix),
StringJoiner::add, StringJoiner::merge,
StringJoiner::toString, CH_NOID);
}


 

Collector.joining的實現原理就是藉助了StringJoiner。

 

當然,或許在Collector中直接使用StringBuilder似乎也可以實現類似的功能,只不過稍微麻煩一些。所以,Java 8中提供了StringJoiner來豐富Stream的用法

 

而且StringJoiner也可以方便的增加字首和字尾,比如我們希望得到的字串是”[Hollis,hollischuang,Java乾貨]”而不是”Hollis,hollischuang,Java乾貨”的話,StringJoiner的優勢就更加明顯了。

 

4

總結

本文介紹了Java 8中提供的可變字串類——StringJoiner,可以用於字串拼接。

StringJoiner其實是透過StringBuilder實現的,所以他的效能和StringBuilder差不多,他也是非執行緒安全的。

如果日常開發中中,需要進行字串拼接,如何選擇?

1、如果只是簡單的字串拼接,考慮直接使用”+”即可。

2、如果是在for迴圈中進行字串拼接,考慮使用StringBuilder和StringBuffer。

3、如果是透過一個集合(如List)進行字串拼接,則考慮使用StringJoiner。

4、如果是對一組資料進行拼接,則可以考慮將其轉換成Stream,並使用StringJoiner處理。

    贊(0)

    分享創造快樂