字符串拼接新姿勢—— Java 8 StringJoiner

前言

平常工做中拼接字符串確定是咱們少不了的操做,最近工做中正好用到了,而後想起前幾天看到的Java 8的一個新類:StringJoiner類,因此今天正好來看一看它的源碼。bash

正文

用法簡介

這個類的用法其實很簡單,咱們能夠看到源碼中給出的例子:app

StringJoiner sj = new StringJoiner(":", "[", "]");
 sj.add("George").add("Sally").add("Fred");
 String desiredString = sj.toString();
複製代碼

咱們把這個字符串最終打印出來:less

[George:Sally:Fred]
複製代碼

因此基本上能看出一點用法了: 經過帶參構造器構造出一個StringJoiner的對象,調用add方法開始拼接字符串,構造器中的參數會決定拼接的字符串的先後綴以及中間的鏈接符,最終調用toString方法轉換爲String對象。ide

一張圖總覽下這個類裏都有些什麼,後面逐一解釋。ui

參數

StringJoiner總共有五個參數:this

private final String prefix;    //前綴
private final String delimiter; //分隔符
private final String suffix;    //後綴
private StringBuilder value;  
private String emptyValue;   
複製代碼

後兩個參數頗有意思spa

private StringBuilder value; 
實際上是Joiner的底層,說到底StringJoiner仍是調用的StringBuiler方法,只是這層封裝里加上了有關於前綴,後綴和鏈接符的操做,讓咱們能夠方便一些。
複製代碼
private String emptyValue;
 emptyValue 你能夠把它看做是當你的StringJoiner對象沒有進行任何add的操做時,調用toString() 方法會return 這個字符串而不是空。具體的用法後面看到setEmptyValue的時候再舉例子。
複製代碼

看下源碼註釋:指針

/*
     * By default, the string consisting of prefix+suffix, returned by
     * toString(), or properties of value, when no elements have yet been added,
     * i.e. when it is empty.  This may be overridden by the user to be some
     * other value including the empty String.
     */
複製代碼
構造器

從大綱裏能夠看到StringJoiner總共有兩個構造器:code

先看參數多的

public StringJoiner(CharSequence delimiter,
                        CharSequence prefix,
                        CharSequence suffix) {
        Objects.requireNonNull(prefix, "The prefix must not be null");
        Objects.requireNonNull(delimiter, "The delimiter must not be null");
        Objects.requireNonNull(suffix, "The suffix must not be null");
        // make defensive copies of arguments
        this.prefix = prefix.toString();
        this.delimiter = delimiter.toString();
        this.suffix = suffix.toString();
        this.emptyValue = this.prefix + this.suffix;
    }
複製代碼

這裏面三個參數分別是前綴後綴和鏈接符,而後這裏有一個操做就是將emptyValue賦值了前綴+後綴的字符串。也就是說當你用了這個構造器的時候,emptyValue就已經有值了,就是前綴+後綴拼接。當你StringJoiner不執行add方法直接toString()時,會return的對象就是你的前綴+後綴。 例子:cdn

public static void main (String [] args) {

		StringJoiner sj = new StringJoiner(":", "[", "]");
		String desiredString = sj.toString();
		System.out.println(desiredString);
	}

複製代碼

這裏打印結果就是[]

再看只有一個參數的構造器:

public StringJoiner(CharSequence delimiter) {
        this(delimiter, "", "");
    }
複製代碼

其實仍是調用的三參構造器,只不過先後綴默認值爲"",也就是沒有先後綴。這種狀況下emptyValue是什麼呢? 其實和上面同樣的,""+""就是"",不難理解。

方法

先看上面提到最多的toString().

@Override
    public String toString() {
        if (value == null) {
            return emptyValue;
        } else {
            if (suffix.equals("")) {
                return value.toString();
            } else {
                int initialLength = value.length();
                String result = value.append(suffix).toString();
                // reset value to pre-append initialLength
                value.setLength(initialLength);
                return result;
            }
        }
    }
複製代碼

當value爲空(也就是StringBuilder爲空)時,會return emptyVaule, 若是不爲空,就會加上一個給你加後綴的操做。固然這裏加後綴你能夠看做一次性的,他在加以前會取一個長度,無論你後綴多長,加完以後會set到初始長度。

知道了後綴是這裏加的,那前綴呢。

來看最核心的 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;
    }
複製代碼

前綴就是在你調用第一個add的時候就加上了,爲何是第一個呢,由於第一次調用add的時候,你的value確定是空的,因此它會走else的邏輯給你構造一個StringBuilder出來,這個時候會把前綴加好。因此你後面無論有幾個add,都是基於一個StringBuilder上在加字符串。當你的value不爲空了,就會給你拼接上鍊接符,最後再拼接上add()方法裏的參數。完美。

再結合toString方法來看,當你沒有調用過add方法而直接toString時,value爲空,它就會return emptyValue了。

再來看個和emptyValue有關的方法setEmptyValue(CharSequence emptyValue):

public StringJoiner setEmptyValue(CharSequence emptyValue) {
        this.emptyValue = Objects.requireNonNull(emptyValue,
            "The empty value must not be null").toString();
        return this;
    }
複製代碼

這個方法實際上是暴露給開發者主動設置emptyValue值的方法,也就是說,當你沒有調用set方法,emptyValue默認值爲前綴+後綴,無論先後綴是否爲空;當你調用了set方法,emptyValue就是設置的值。 舉個例子:

public static void main (String [] args) {

		StringJoiner sj = new StringJoiner(":", "[", "]");
		sj.setEmptyValue("anson");
		String desiredString = sj.toString();
		System.out.println(desiredString);
	}
複製代碼

這裏的打印結果就是anson,注意不是[anson]哦。

還有一個有關字符串操做的方法 merge(StringJoiner)

public StringJoiner merge(StringJoiner other) {
        Objects.requireNonNull(other);
        if (other.value != null) {
            final int length = other.value.length();
            // lock the length so that we can seize the data to be appended
            // before initiate copying to avoid interference, especially when
            // merge 'this'
            StringBuilder builder = prepareBuilder();
            builder.append(other.value, other.prefix.length(), length);
        }
        return this;
    }
複製代碼

這裏面調用了一個StringBuilder的append()重載方法:

public StringBuilder append(CharSequence s, int start, int end) {
        super.append(s, start, end);
        return this;
    }
複製代碼

也就是說merge操做是把另外一個StringJoiner(簡稱sj2)的從前綴開始(不包括前綴)包括鏈接符可是不包括後綴的字符串加進去sj1裏面。

上個例子:

public static void main (String [] args) {

		StringJoiner sj1 = new StringJoiner(":","[","]");
		StringJoiner sj2 = new StringJoiner(",","{","}");
		sj1.add("b");
		sj2.add("a").add("c");
		sj1.merge(sj2);
		String desiredString = sj1.toString();
		System.out.println(desiredString);
	}
複製代碼

打印結果:[b:a,c]

先後綴都是sj1的,ac間的鏈接符是sj2的。

最後再看個簡單的方法收尾

public int length() {
        // Remember that we never actually append the suffix unless we return
        // the full (present) value or some sub-string or length of it, so that
        // we can add on more if we need to.
        return (value != null ? value.length() + suffix.length() :
                emptyValue.length());
    }
複製代碼

length()方法你們最熟悉,獲取長度。這裏能看到有一個好處就是當你沒有調用add方法也就是沒有初始化StringBuilder時,調用這個方法不會空指針,由於有默認的emptyValue。

總結

總結一下,Java 8的新類StringJoiner用法很簡單,其實就是一個披着StringJoiner皮的StringBuilder而已嘛。不過有人幫你封裝好了加減後綴和鏈接符的方法也是好的!

相關文章
相關標籤/搜索