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) {
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;
private StringBuilder value;
private 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();
this.emptyValue = this.prefix + this.suffix;
}
3. setEmptyValue()
public StringJoiner setEmptyValue(CharSequence emptyValue) {
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) {
value.append(delimiter);
} else {
value = new StringBuilder().append(prefix);
}
return value;
}
5. 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();
value.setLength(initialLength);
return result;
}
}
}
6. merge()
public StringJoiner merge(StringJoiner other) {
Objects.requireNonNull(other);
if (other.value != null) {
final int length = other.value.length();
StringBuilder builder = prepareBuilder();
builder.append(other.value, other.prefix.length(), length);
}
return this;
}
7. length()
public int length() {
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:
@Override
public String toString() {
return 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 = 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.setLength(initialLength);
return result;
}
因此在StringJoiner的length()方法里面才有 加上后缀长度的逻辑。 为什么要这样子设计了? 根据在length()方法里面的注释:
public int length() {
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结束了,显然不是设计的初衷
|