Guava学习笔记(3)Joiner

2018-05-22  本文已影响0人  懵逼猴

Joiner的作用

常见用法

    Joiner joiner = Joiner.on("; ").skipNulls();
    String joinStr = joiner.join("Harry", null, "Ron", "Hermione");
    //return info:Harry; Ron; Hermione
    System.out.println(joinStr);

    String listStr =Joiner.on(",").join(Arrays.asList(1, 5, 7));
    //return info:"1,5,7"
    System.out.println(listStr);

源码解析

Joiner对象的构造

Joiner为了保证是线程安全的,它的每一个实例都是不可变得immutable,他的构造函数都是私有的,只能使用提供的静态方法进行实例化。

// 构造方法
private Joiner(String separator) {
    this.separator = checkNotNull(separator);
  }
  private Joiner(Joiner prototype) {
    this.separator = prototype.separator;
  }
// 通过静态方法获取Joiner示例
 public static Joiner on(String separator) {
    return new Joiner(separator);
  }
  public static Joiner on(char separator) {
    return new Joiner(String.valueOf(separator));
  }

实例化之后里面的属性就能修改,每一次修改变量都是返回一个新的对象,而且这两个变量只能是指一个,同时设置两个的话会抛出UnsupportedOperationException错误,skipNulls方法的代码类似

return new Joiner(this) {
      @Override
      CharSequence toString(@Nullable Object part) {
        return (part == null) ? nullText : Joiner.this.toString(part);
      }
      @Override
      public Joiner useForNull(String nullText) {
        throw new UnsupportedOperationException("already specified useForNull");
      }
      @Override
      public Joiner skipNulls() {
        throw new UnsupportedOperationException("already specified useForNull");
      }

从上面的代码中可以看出useForNull这个方法的跳过其实就是生成了一个重写了toString方法的的类,如果是null则返回用户指定代替的类。

对象的拼接

下面来看一下,Joiner如何实现对象的拼接,其中最主要的方法是下面的这个方法,其他的所有方法都是之间或者间接的调用这个方法来实现功能的。

public <A extends Appendable> A appendTo(A appendable, Iterator<?> parts) throws IOException {
    checkNotNull(appendable);
    // 对n个值两两之间添加字符等信息可以借鉴这种方法
    if (parts.hasNext()) {
      // 对每一个拼接的单元使用toString方法的返回值进行拼接,toString默认使用非CharSequence实例的toString作为返回值,所以可以重写toString方法来对空格进行替换。
      appendable.append(toString(parts.next()));
      while (parts.hasNext()) {
        appendable.append(separator);
        appendable.append(toString(parts.next()));
      }
    }
    return appendable;
  }

skipNulls的实现方式则是重写了appendTo方法,代码如下:

public <A extends Appendable> A appendTo(A appendable, Iterator<?> parts) throws IOException {
        // 参数合法性检查
        checkNotNull(appendable, "appendable");
        checkNotNull(parts, "parts");
       // 跳过前面所有的null直到遇到第一个非null值
        while (parts.hasNext()) {
          Object part = parts.next();
          if (part != null) {
            appendable.append(Joiner.this.toString(part));
            break;
          }
        }
        // 对后面的单元进行处理
        while (parts.hasNext()) {
          Object part = parts.next();
          if (part != null) {
            appendable.append(separator);
            appendable.append(Joiner.this.toString(part));
          }
        }
        return appendable;
      }

拼接map形式的数据结构

通过调用withKeyValueSeparator放回一个MapJoiner内部类的对象,通过下面的方法实现数据的拼接,和拼接list类型的操作类似,代码如下不在详述。

 public <A extends Appendable> A appendTo(A appendable, Iterator<? extends Entry<?, ?>> parts)
        throws IOException {
      checkNotNull(appendable);
      if (parts.hasNext()) {
        Entry<?, ?> entry = parts.next();
        appendable.append(joiner.toString(entry.getKey()));
        appendable.append(keyValueSeparator);
        appendable.append(joiner.toString(entry.getValue()));
        while (parts.hasNext()) {
          appendable.append(joiner.separator);
          Entry<?, ?> e = parts.next();
          appendable.append(joiner.toString(e.getKey()));
          appendable.append(keyValueSeparator);
          appendable.append(joiner.toString(e.getValue()));
        }
      }
      return appendable;
    }
上一篇下一篇

猜你喜欢

热点阅读