StringJoiner拼接字符串(使用以及源码解析)
文章目錄
- 1. 介紹
- 2. 代碼演示
- 3. 源碼
- 1. 成員變量
- 2. 構造函數
- 3. setEmptyValue()
- 4. add()
- 5. toString()
- 6. merge()
- 7. length()
- 8. 再次詳細解釋toString(),跟length()方法
1. 介紹
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會自動幫你加上前綴后綴的長度。
返回的是前后綴字符串拼接,因為在StringJoiner有個成員變量是emptyValue,若不指定,默認是 emptyValue = 前綴符+后綴符,而出來沒有add過其他字符串,因此返回默認值emptyValue。
發現指定了默認值,則不會返回前綴+后綴字符串了,因為重置了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:
代碼例子:
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()方法里面的注釋:
翻譯可以得:就是可以隨時想添加新的字符串都可以。
代碼:
可以想一想,如果toString里面沒有重置value(StringBuilder)的長度,那么你toString之后,豈不是再add的時候,應該是 AB,C結束了,D,F結束了,顯然不是設計的初衷
總結
以上是生活随笔為你收集整理的StringJoiner拼接字符串(使用以及源码解析)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Product UVA - 10106(
- 下一篇: 解决socket:(10106)无法加载