美文网首页
Guava-Joiner

Guava-Joiner

作者: 63f4fe6cfa47 | 来源:发表于2022-03-11 00:58 被阅读0次

Joiner

只提供两个静态方法,参数是分隔符。静态方法内部new一个自身对象,返回该对象,之后可以通过该对象访问非静态方法和访问非静态数据

//方法一
public static Joiner on(String separator) {
    return new Joiner(separator);
}
//方法二
public static Joiner on(char separator) {
    return new Joiner(String.valueOf(separator));
}

两个私有有参构造(一个参数是分隔符,一个参数是对象自身类型)

  private Joiner(String separator) {
    this.separator = checkNotNull(separator);
  }

  private Joiner(Joiner prototype) {
    this.separator = prototype.separator;
  }

测试skipNulls:

//添加分隔符
Joiner joiner = Joiner.on("*");
//重写了appendTo方法,允许参数有null值
joiner = joiner.skipNulls();
//调用重写后的appendTo方法拼接参数
String join = joiner.join(Lists.newArrayList("aaa", "bbb", "ccc", null, "ddd"));
System.out.println(join);
//输出aaa*bbb*ccc*ddd

第一步,通过调用静态方法,静态方法内部通过有参构造生成一个新的Joiner对象
第二步,执行skipNulls方法,该方法生成一个新的Joiner对象,将原先的分隔符赋值给新的Joiner对象,且重写了apperdTo方法,。重写后的方法就在原先apperdTo方法的基础上,加了null值的判断,如果为null就跳过。此时该方法流程是:

  • 非空判断拼接的流对象和虚拼接的数组对象
  • 进入第一个循环,直到拿到不为null的元素后跳出
  • 进入第二个循环,每当拿到不为null的元素时,都先拼接分隔符,再拼接元素值
  • 最后拼接返回结果
    ps:如果是没有重写的appendTo方法,不会进行null,判断,直接执行字符串的拼接append方法,如果遇到null,就会抛出空指针异常
  public Joiner skipNulls() {
    return new Joiner(this) {
      @Override
      public <A extends Appendable> A appendTo(
          A appendable, Iterator<? extends @Nullable Object> parts) throws IOException {
        checkNotNull(appendable, "appendable");
        checkNotNull(parts, "parts");
        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;
      }

      @Override
      public Joiner useForNull(String nullText) {
        throw new UnsupportedOperationException("already specified skipNulls");
      }

      @Override
      public MapJoiner withKeyValueSeparator(String kvs) {
        throw new UnsupportedOperationException("can't use .skipNulls() with maps");
      }
    };
  }

测试useForNull:

        //添加分隔符
        Joiner joiner = Joiner.on("*");
        //将null替换为指定值
        joiner = joiner.useForNull("XXX");
        String join = joiner.join(Lists.newArrayList("aaa", "bbb", "ccc", null, "ddd"));
        System.out.println(join);
        //输出aaa*bbb*ccc*XXX*ddd

该方法在原先未重写appendTo方法的基础上重写了toString方法,本身为重写appendTo方法是不会跳过null值,重写后的toString方法就会将null值替换为指定的值

  public Joiner useForNull(String nullText) {
    checkNotNull(nullText);
    return new Joiner(this) {
      @Override
      CharSequence toString(@CheckForNull 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:

        Joiner joiner = Joiner.on("*");
        Map<String,String> map = new HashMap<>();
        map.put("aaa","bbb");
        map.put("ccc",null);
        map.put("ddd","eee");
        String result = joiner.withKeyValueSeparator("XXX").useForNull("LLL").join(map);
        System.out.println(result);
        //输出aaaXXXbbb*cccXXXLLL*dddXXXeee

该方法可以将map集合改为 key+分隔符+value格式,配合useForNull,可以将value等于null的值替换为指定值

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

迭代获取每个map元素,进行拼接,同理,如果执行了useForNull方法,会重写toString方法,将null值替换为指定值
思考:

  1. 为什么需要通过静态方法调用构造方法来生成对象,访问非静态方法和非静态成员
  • 使用静态工厂模式
  • 减少对外暴露的属性
  1. 线程安全性
    由于每次调用on方法时,返回的都是一个新的构造对象,后续的非静态方法都是依赖新的对象,所以不存在线程安全问题

相关文章

  • Guava-Joiner

    Joiner 只提供两个静态方法,参数是分隔符。静态方法内部new一个自身对象,返回该对象,之后可以通过该对象访问...

  • 效率提升神器之Guava-Joiner

    在我们的开发中经常会用到Guava中的一些功能。但是我们所使用到的只是Guava API中的小的可怜的一个子集。我...

网友评论

      本文标题:Guava-Joiner

      本文链接:https://www.haomeiwen.com/subject/ttaqdrtx.html