JDK8-StringJoiner详解

StringJoiner产生的原因

  • 现有的字符串连接方法要实现连接时对结果字符串加入前缀、后缀和分隔符相对比较麻烦。

包含的成员变量和方法

成员变量

    private final String prefix;  //前缀
    private final String delimiter;  //分隔符(可以是字符串)
    private final String suffix;   //后缀
    private StringBuilder value;
	//当value为空时的返回值
    private String emptyValue;
  • 无论何时,value里面的字符串都不包括后缀,只包含前缀和用分隔符分割的字符串,这样可以在继续向里面添加字符串时不必删除后缀(包含了循环不变式的思想)。

构造方法

StringJoiner(CharSequence delimiter)

    //将前缀和后缀设为空   
	public StringJoiner(CharSequence delimiter) {
        this(delimiter, "", "");
    }

StringJoiner(CharSequence delimiter,CharSequence prefix,CharSequence suffix)

    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;
    }

常用的方法

添加元素——add()和prepareBuilder()

    public StringJoiner add(CharSequence newElement) {
        
        prepareBuilder().append(newElement);
        return this;
    }

    private StringBuilder prepareBuilder() {
        if (value != null) {
            //已经有元素的情况下,先添加分隔符
            value.append(delimiter);
        } else {
            //在没有元素的情况下,新建一个StringBuilder对象,并添加前缀
            value = new StringBuilder().append(prefix);
        }
        return value;
    }
  • 从构造函数和类变量的声明可以看出,没有添加元素前stringbuilder是没有初始化的;反之,应注意,value为空指的并不是里面没有元素,而是没有初始化

toString()

    @Override
    public String toString() {
        if (value == null) {
            //如果value为空,则返回emptyValue
            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;
            }
        }
    }
  • 个人认为第一层else里面的代码与“return value.toString().concat(suffix);”有相同的效果,此时添加后缀不会影响value的长度。

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;
    }

这种设计的原因可能基于以下的情况(将append()方法里的length替换为other.value.length()):

    public StringJoiner merge(StringJoiner other) {
        Objects.requireNonNull(other);
        if (other.value != null) {
            
            StringBuilder builder = prepareBuilder();
            builder.append(other.value, other.prefix.length(), other.value.length());
            
        }
        return this;
    }

如果依照以上的代码执行自我合并,当执行了prepareBuilder()方法后,value中将增加一个分隔符,由于要合并的对象和被合并的对象是同一个对象,若使用以上的方法进行合并,合并完成后,value的末尾将多出一个分隔符,若之后再使用该对象的add()方法,将出现问题。

不常用的方法

setEmptyValue

    public StringJoiner setEmptyValue(CharSequence emptyValue) {
        this.emptyValue = Objects.requireNonNull(emptyValue,
            "The empty value must not be null").toString();
        return this;
    }
  • 作用为自定义emptyValue;
  • 若形参emptyValue仍为空,则抛出异常,提示The empty value must not be null。

length()

    public int length() {
        return (value != null ? value.length() + suffix.length() :
                emptyValue.length());
    }
  • 若当前的value不为空,则返回value的长度+后缀长度的和;
  • 否则返回emptyValue的长度。

注意

  • StringJoiner类是基于StringBuilder类的;
  • value的空指的是未初始化,而并非value里不含元素。

参考

https://www.jianshu.com/p/469fe8fdd3be

你可能感兴趣的:(java语言)