Java8之StringJoiner
中午躺在床上,闲来无事草草看了一眼微信,无意间发现了一篇技术文章,讲的是StringJoiner的运用。
当时第一反应就是这玩意大概又是java8以上版本新出的东西吧?细看发现并不是,居然是java8中存在的一个用于构建字符串的类。以前居然完全没听说过... ...惊叹之余,决定必须学一波。
由于这个类比较简单,所以可以直接看着源码学习。
private final String prefix; private final String delimiter; private final String suffix; private StringBuilder value; private String emptyValue;
首先来看一下类中存在的五个成员变量,依次为前缀、分隔符、后缀、用于处理字符串的StringBuilder、和空值(是这么翻译吧?)
看到这里大概就反应过来了,原来这个类是对于StringBuilder的再次封装。
然后,会发现紧随其后的是两个构造方法
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"); // make defensive copies of arguments this.prefix = prefix.toString(); this.delimiter = delimiter.toString(); this.suffix = suffix.toString(); this.emptyValue = this.prefix + this.suffix; }
可见第一个构造器内部调用了第二个构造器,将第二个构造器的两个参数设为默认值“”,第二个构造器实际上就是需要使用者传入分隔符、前缀、后缀,并且空值被设为前缀加后缀。
看到这里大概可以猜测到空值的作用就是在StringJoiner没有添加任何字符串的情况下,得到的最终值。
public StringJoiner setEmptyValue(CharSequence emptyValue) { this.emptyValue = Objects.requireNonNull(emptyValue, "The empty value must not be null").toString(); return this; }
设置空值,这个方法没什么好说的
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对象,如果为null,那么直接返回空值。
如果后缀为“”,直接返回value的toString(),如果后缀不为“”,那么需要将后缀拼接好然后一并返回。
public StringJoiner add(CharSequence newElement) { prepareBuilder().append(newElement); return this; }
然后是比较常用的add方法,内部调用了prepareBuilder()方法,最后返回对象本身,也就实现了链式调用。
private StringBuilder prepareBuilder() { if (value != null) { value.append(delimiter); } else { value = new StringBuilder().append(prefix); } return value; }
prepareBuilder()方法也比较简单,如果没有StringBuilder对象,那么就创建一个然后添加前缀,如果有,则添加分隔符,返回StringBuilder对象本身。
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; }
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());
}
这两个方法好像也没啥好说的... ...
既然StringJoiner实际上使用的仍然是StringBuilder,而在源码中没有发现对于线程安全的处理,那么它应该也是非线程安全的。