日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

StringJoiner拼接字符串(使用以及源码解析)

發布時間:2023/12/18 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 StringJoiner拼接字符串(使用以及源码解析) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 1. 介紹
  • 2. 代碼演示
  • 3. 源碼
    • 1. 成員變量
    • 2. 構造函數
    • 3. setEmptyValue()
    • 4. add()
    • 5. toString()
    • 6. merge()
    • 7. length()
    • 8. 再次詳細解釋toString(),跟length()方法

1. 介紹

  • StringJoiner類是jdk8推出的,用于構造由分隔符分隔字符序列,并可選擇性地從提供的前綴開始和以提供的后綴結尾
  • 說的通俗一點:就是讓字符串之間有分隔符或者字符串有前綴或者后綴,不用開發人員自己拼接。
  • 2. 代碼演示

    public class demo {public static void main(String[] args) {// 第一個參數:分隔符StringJoiner stringJoiner = new StringJoiner(",");stringJoiner.add("hello").add("world");System.out.println(stringJoiner.toString());System.out.println(stringJoiner.length());} }

    public class demo {public static void main(String[] args) {// 第一個參數:分隔符// 第二個參數:前綴符// 第三個參數:后綴符StringJoiner stringJoiner = new StringJoiner(",","kk","dd");stringJoiner.add("hello").add("world");System.out.println(stringJoiner.toString());System.out.println(stringJoiner.length());} }


    細心的人發現:加了前綴kk,后綴dd,字符串長度從剛剛的11變成了15,即StringJoiner會自動幫你加上前綴后綴的長度。

    public class demo {public static void main(String[] args) {// 不add字符串,看看會返回什么StringJoiner stringJoiner = new StringJoiner(",","kk","dd");System.out.println(stringJoiner.toString());System.out.println(stringJoiner.length());} }


    返回的是前后綴字符串拼接,因為在StringJoiner有個成員變量是emptyValue,若不指定,默認是 emptyValue = 前綴符+后綴符,而出來沒有add過其他字符串,因此返回默認值emptyValue。

    public class demo {public static void main(String[] args) {// 指定默認值StringJoiner stringJoiner = new StringJoiner(",","kk","dd");stringJoiner.setEmptyValue("我是默認值");System.out.println(stringJoiner.toString());System.out.println(stringJoiner.length());} }


    發現指定了默認值,則不會返回前綴+后綴字符串了,因為重置了emptyValue值,返回固然是設置的值,長度更加不用多說吧
    具體原因請看下面源碼解析:

    3. 源碼

    1. 成員變量

    // 前綴字符private final String prefix;// 分隔字符private final String delimiter;// 后綴字符private final String suffix;// 拼接結果,注類型是StringBuilderprivate StringBuilder value;// 默認值,當new StringJoiner時,沒有add其他字符串// 此時toString,返回的就是emptyValueprivate String emptyValue;

    2. 構造函數

    // 指定分隔符,前后綴默認為"" public StringJoiner(CharSequence delimiter) {this(delimiter, "", ""); }// 指定分隔符,前后綴符 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");this.prefix = prefix.toString();this.delimiter = delimiter.toString();this.suffix = suffix.toString();// 此時 emptyValue是前后綴符的拼接this.emptyValue = this.prefix + this.suffix; }

    3. setEmptyValue()

    public StringJoiner setEmptyValue(CharSequence emptyValue) {// 從上述構造函數可以看出,默認值是前后綴符的拼接// 還可以使用setEmptyValue 設置自定義默認值this.emptyValue = Objects.requireNonNull(emptyValue,"The empty value must not be null").toString();return this; }

    4. add()

    public StringJoiner add(CharSequence newElement) {// 添加字符串prepareBuilder().append(newElement);return this;}private StringBuilder prepareBuilder() {if (value != null) {// 在添加新的String的時候,先添加分隔符value.append(delimiter);} else {// 如果value還沒有被構造,說明是第一次add// 第一次add,當然要先new StringBuilder(),并且加前綴// 也可以看出 value是懶加載,不用就不new// 當然這樣子做的原因也是為了區分是否第一次add,才能合理判斷是加前綴,還是分隔符。value = new StringBuilder().append(prefix);}return value;}

    5. toString()

    @Overridepublic String toString() {// 根據上面add()源碼可以知道,只有第一次add了,才會new StringBuild// 因此 value == null 說明從來沒有add字符串過if (value == null) {// 因此返回的是默認值// 若沒有setEmptyValue過,則返回前后綴字符串拼接的值// 若設置過,則返回設置的值return emptyValue;} else {// 走到這里,說明已經add過了// 此時判斷后綴是否為空串if (suffix.equals("")) {return value.toString();} else {// 注意:這里是StringBuilder的length()方法// 此時 value 里面有前綴,add的字符串,可能還有分隔符// 此時的initialLength 長度沒有算上后綴字符串int initialLength = value.length();// 現在將后綴加上,value.length()此時是5// 注意:此時的toString方法是StringBuilder類的String result = value.append(suffix).toString();// 這里卻重置了,雖然 value里面包括后綴,但是長度沒有算進去// 即 value.length()等于 實際長度減后綴符長度// 也就是 value里面不算上后綴符,本文最后再詳細解析value.setLength(initialLength);return result;}}}

    6. merge()

    // 合并兩個StringJoiner public StringJoiner merge(StringJoiner other) {Objects.requireNonNull(other);if (other.value != null) {// 根據上面toString解析,知道value.length() 是不包括后綴的長度final int length = other.value.length();// 先在原來的value 加上 分隔符StringBuilder builder = prepareBuilder();// 再把other的字符串 添加到value里面// 可以看出,排除了other的前綴符builder.append(other.value, other.prefix.length(), length);}return this;}

    7. 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.// 調用StringJoiner的toString方法,此時算上后綴符長度// 若沒有add過,則返回默認值的長度return (value != null ? value.length() + suffix.length() :emptyValue.length());}

    8. 再次詳細解釋toString(),跟length()方法

    上文中說到toString中有下面的邏輯:

    if (suffix.equals("")) {return value.toString();} else {int initialLength = value.length();String result = value.append(suffix).toString();value.setLength(initialLength);return result;}

    首先要明確:value.length() 與 value.append(suffix).toString() 與 value.setLength(initialLength); 調用的是StringBuilder的方法。
    在StringBuilder中的toString與setLength

    @Overridepublic String toString() {// 它是new String,指定了范圍的// 打個比方:如果value為ABC// new String(value,0,1) 則返回是Areturn new String(value, 0, count);}public void setLength(int newLength) {if (newLength < 0)throw new StringIndexOutOfBoundsException(newLength);ensureCapacityInternal(newLength);if (count < newLength) {Arrays.fill(value, count, newLength, '\0');}// count就是你設置的大小count = newLength;}

    代碼例子:

    public class demo {public static void main(String[] args) {StringBuilder builder = new StringBuilder();builder.append("ABC");builder.setLength(1);System.out.println(builder.toString());} }


    發現 只返回A,實際上builder里面是ABC,但是重置了length即重置了count,因此BC相當于沒有了。

    重新回到這里StringJoiner的toString方法里面某個片段:

    if (suffix.equals("")) {return value.toString();} else {int initialLength = value.length();String result = value.append(suffix).toString();// value里面雖然在上一步加上了后綴字符串// 但是這里重置了length,相當于 value 沒有加上后綴字符串value.setLength(initialLength);return result;}

    因此在StringJoiner的length()方法里面才有 加上后綴長度的邏輯。
    為什么要這樣子設計了?
    根據在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());}

    翻譯可以得:就是可以隨時想添加新的字符串都可以。
    代碼:

    public class demo {public static void main(String[] args) {StringJoiner stringJoiner = new StringJoiner(",", "A", "結束了");stringJoiner.add("B").add("C");System.out.println(stringJoiner.toString());System.out.println(stringJoiner.length());stringJoiner.add("D").add("F");System.out.println(stringJoiner.toString());System.out.println(stringJoiner.length());} }


    可以想一想,如果toString里面沒有重置value(StringBuilder)的長度,那么你toString之后,豈不是再add的時候,應該是 AB,C結束了,D,F結束了,顯然不是設計的初衷

    總結

    以上是生活随笔為你收集整理的StringJoiner拼接字符串(使用以及源码解析)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。