日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

放棄 StringBuilder!Java8的StringJoiner,真香

 

為什么會新增這樣一個string輔助類?

原有的stringbuilder太死板,不支持分割,如果想讓最終的字符串以逗號隔開,需要這樣寫


StringBuilder sb = new StringBuilder();
IntStream.range(1,10).forEach(i->{
    sb.Append(i+"");
    if( i < 10){
        sb.append(",")
    } 
});

是不是太死板了,不好用,StringJoiner怎樣寫呢?

StringJoiner sj = new StringJoiner(",");
IntStream.range(1,10).forEach(i->sj.add(i+""));

有哪些平時用得還比較少的功能:

  • setEmptyValue, 默認情況下的emptyValue是前綴加后綴, 用戶可自定義emptyValue
  • merge(StringJoiner other),合并另外一個joiner
  • length, 當前長度,為空看emptyValue的長度

讓我實現StringJoiner,我會怎么辦呢?

  • 維護一個List,最后toString的時候join一下就好了
    優勢:實現非常方便缺點:list太浪費空間(擴容時都是按照系數擴容的)
  • 在StringBuilder基礎上改造(jdk實現方式就是以組合的形式增強的StringBuilder)

jdk實現的源碼分析

  • 成員變量
    private final String prefix;
    private final String delimiter;
    private final String suffix;

    /*
     * StringBuilder value -- at any time, the characters constructed from the
     * prefix, the added element separated by the delimiter, but without the
     * suffix, so that we can more easily add elements without having to jigger
     * the suffix each time.
     */
    private StringBuilder value;

    /*
     * 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.
     */
    private String emptyValue;

其實從成員變量的注釋里就能看出他們的作用和需要注意的點了

  • 構造函數
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();
        // !!!構造時就直接將emptyValue拼接好了。
        this.emptyValue = this.prefix + this.suffix;
    }

為什么要一開始就構造好呢?如果我想直接自定義emptyValue直接用構造函數初始化不是更方便嗎?是因為絕大多數場景下都不會自定義emptyValue的場景嗎?不對啊,感覺這個場景非常必要啊。。。

  • 添加元素
public StringJoiner add(CharSequence newElement) {
        prepareBuilder().append(newElement);
        return this;
}

private StringBuilder prepareBuilder() {
        // 從構造函數和類變量的聲明可以看出,沒有添加元素前stringbuilder是沒有初始化的
        if (value != null) {
            // 已經有元素存在的情況下,添加元素前先將分隔符添加進去
            value.append(delimiter);
        } else {
            // 沒有元素存在的情況下先把前綴加進去
            value = new StringBuilder().append(prefix);
        }
        return value;
}

可以看出在添加元素的過程中就已經把前綴和分割字符什么的都處理好了,全部都在stringbuilde中了,唯一沒有處理的就是后綴。 為什么?這樣做tostring什么的時候真的超級方便的有木有。。。。。

  • 關鍵的toString
public String toString() {
        if (value == null) {
            // 這里如果沒有自定義空值就是前綴+后綴咯。。
            return emptyValue;
        } else {
            // 為什么不直接value.toString()+suffix?????
            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.toString()+suffix?答案在merge方法

  • merge
public StringJoiner merge(StringJoiner other) {
        Objects.requireNonNull(other);
        if (other.value != null) {
            final int length = other.value.length();
            // 下面這段注釋是說避免merge(this)時受影響,為什么?
            // 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;
    }

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

merge的思路是用當前的striingBuilder去append other的value(必須去掉前綴),源碼注釋中的merge 'this'問題是什么呢? prepareBuilder()的時候可能會先append(delimiter),如果other就是this,那么length其實就多了一個delimiter,此時append還是得以添加前的length為準。

merge的實現方式決定了toString時不能直接value.append(suffix).toString(),因為
builder.append(other.value, other.prefix.length(), length);這行代碼,默認加上suffix后這里的merge的length得減去suffix的length(嗯,看來作者是想得多好多),而且merge時得把另外一個sj的內容append到當前這個sj的suffix之前(想想就麻煩多了。。。。)

  • length
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的元素的length,還有前后綴。

總結

  • 基于StringBuilder實現,add時就把prefix和分隔符給加上了,suffix永遠都不加,知道toString和length調用時才加入計算。 這樣帶來的merge操作實現的極大便利性!!!!!學到了,真的不錯
  • emptyValue這個一定要構造時就生成嗎?用戶想有自己的默認值還需要先構造實例再注入嗎。。。。這個覺得還是有點奇怪
  • Objects這個工具方法是返回的校驗的值本身,不錯。
public StringJoiner setEmptyValue(CharSequence emptyValue) {
// 注意這個Objects.requireNonNull方法是return的第一個參數。。。
        this.emptyValue = Objects.requireNonNull(emptyValue,
            "The empty value must not be null").toString();
        return this;
}

作者:炫邁哥
鏈接:
https://www.jianshu.com/p/469fe8fdd3be

分享到:
標簽:Java8
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定