引言

StringJoiner是java.util包下的一个类,在String.join()方法方法以及java.util.stream类的一些方法中会被用到,总体来说,这个类是比较简单的,我们来分析一下这个类的实现。

用途描述

先看源码中的注释来理解一下这个类的用途:

  1. /**
  2. * {@code StringJoiner} is used to construct a sequence of characters separated
  3. * by a delimiter and optionally starting with a supplied prefix
  4. * and ending with a supplied suffix.
  5. * <p>
  6. * Prior to adding something to the {@code StringJoiner}, its
  7. * {@code sj.toString()} method will, by default, return {@code prefix + suffix}.
  8. * However, if the {@code setEmptyValue} method is called, the {@code emptyValue}
  9. * supplied will be returned instead. This can be used, for example, when
  10. * creating a string using set notation to indicate an empty set, i.e.
  11. * <code>"{}"</code>, where the {@code prefix} is <code>"{"</code>, the
  12. * {@code suffix} is <code>"}"</code> and nothing has been added to the
  13. * {@code StringJoiner}.

StringJoiner用来构造一个字符数组,这个数组被一个分隔符delimiter分隔,并且有一个可选的前缀prefix和一个可选的后缀suffix。在向StringJoiner增加一些东西之前,它的toString方法,会默认返回前缀+后缀即prefix+suffix,如果setEmptyValue方法被调用,toString方法会返回emptyValue。当使用字符串表示一个空的集合时,例如{},时可以被用到。

成员变量和构造方法

  1. private final String prefix;
  2. private final String delimiter;
  3. private final String suffix;
  4. private StringBuilder value;
  5. private String emptyValue;

前缀prefix、分隔符delimiter和后缀suffix肯定都得有,然后可以通过emptyValue指定默认的值。value是一个StringBuilder,用这个StringBuilder来进行字符串的拼接。
再看构造方法:

  1. public StringJoiner(CharSequence delimiter) {
  2. this(delimiter, "", "");
  3. }
  4. public StringJoiner(CharSequence delimiter,
  5. CharSequence prefix,
  6. CharSequence suffix) {
  7. Objects.requireNonNull(prefix, "The prefix must not be null");
  8. Objects.requireNonNull(delimiter, "The delimiter must not be null");
  9. Objects.requireNonNull(suffix, "The suffix must not be null");
  10. // make defensive copies of arguments
  11. this.prefix = prefix.toString();
  12. this.delimiter = delimiter.toString();
  13. this.suffix = suffix.toString();
  14. this.emptyValue = this.prefix + this.suffix;
  15. }

两个构造方法,前者调用的是后者,后者分别设置前缀prefix、后缀suffix和分隔符delimiter,同时会设置emptyValue为prefix+suffix,也就是说emptyValue默认是prefix+suffix。你也可以调用下面的方法来设置emptyValue的值:

  1. public StringJoiner setEmptyValue(CharSequence emptyValue) {
  2. this.emptyValue = Objects.requireNonNull(emptyValue,
  3. "The empty value must not be null").toString();
  4. return this;
  5. }

字符串的拼接

add方法用来实现字符串的拼接:

  1. private StringBuilder prepareBuilder() {
  2. if (value != null) {
  3. value.append(delimiter);
  4. } else {
  5. value = new StringBuilder().append(prefix);
  6. }
  7. return value;
  8. }

add方法实际上是调用了StringBuilder的append方法来实现字符串的拼接,prepareBuilder方法如下:

  1. private StringBuilder prepareBuilder() {
  2. if (value != null) {
  3. value.append(delimiter);
  4. } else {
  5. value = new StringBuilder().append(prefix);
  6. }
  7. return value;
  8. }

逻辑也很简单,如果value也就是StringBuilder为null,就会创建一个新的StringBuilder并默认将prefix添加进去,否则,就调用StringBuilder的append方法将分隔符添加进去,所以StringBuilder中是没有suffix的,这样是为了每次执行add方法不用去管suffix。

toString方法

  1. @Override
  2. public String toString() {
  3. if (value == null) {
  4. return emptyValue;
  5. } else {
  6. if (suffix.equals("")) {
  7. return value.toString();
  8. } else {
  9. int initialLength = value.length();
  10. String result = value.append(suffix).toString();
  11. // reset value to pre-append initialLength
  12. value.setLength(initialLength);
  13. return result;
  14. }
  15. }
  16. }

如果value也就是StringBuilder为空,也就是还没有添加任何东西,就返回emptyValue,否则判断suffix是否为空字符串,如果是空字符串,直接返回StringBuilder.toString(),因为StringBuilder中没有suffix,所以这样返回没有问题,如果suffix不是空字符串,就需要将suffix添加到StringBuilder然后返回StringBuilder.toString()。