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,而在源码中没有发现对于线程安全的处理,那么它应该也是非线程安全的。

原文地址:https://www.cnblogs.com/wxdmw/p/13999557.html