版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/dancheng1/article/details/84819034
将字符串数组按指定分隔符连接起来,或字符串串按指定索引开始使用指定分隔符连接起来
变量
//分割符
private final String separator;
构造方法
两个构造函数都是静态构造器,所以不能直接使用这两个构造器去创建Joiner,所以想要创建Joiner只能使用静态方法。
可接收字符串和字符,字符串可以为空,字符不可为空字符
private Joiner(String separator) {
//对字符判空
this.separator = (String)Preconditions.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));
}
这两个方法一个传入字符串,一个传入字符,然后直接分别使用两个构造器构造
功能函数
这些功能函数都是非静态的需要在Joiner对象的调用下使用
join()方法
对于4个join方法实际可以分为两类,一类是join实现类,另一类是join解析参数类
解析参数类:
//因为 Iterable是所有集合类的顶级接口(除了Map系列),所以此参数为集合类或实现Iterable的类即可
public final String join(Iterable<?> parts) {
//调用join实现类
return this.join((Iterator)parts.iterator());
}
//传入数组
public final String join(Object[] parts) {
//将数组转为ArrayList然后强转为Iterable
return this.join((Iterable)Arrays.asList(parts));
}
//传入两个参数和一个数组,最终这两个参数个数组一起构成一个新的数组
public final String join(@Nullable Object first, @Nullable Object second, Object... rest) {
//使用iterable方法将参数和数组融合成一个数组
return this.join((Iterable)iterable(first, second, rest));
}
由于join第三个实现方法需要 iterable方法对数组进行融合,所以看一下 iterable的实现方式:
private static Iterable<Object> iterable(final Object first, final Object second, final Object[] rest) {
Preconditions.checkNotNull(rest);
//返回一个AbstractList对象,并且这个对象重写了size和get方法
return new AbstractList() {
//使得当前容量比rest数组多2个
public int size() {
return rest.length + 2;
}
public Object get(int index) {
switch(index) {
case 0:
return first;
case 1:
return second;
default:
return rest[index - 2];
}
}};
}
join实现类
public final String join(Iterator<?> parts) {
//实际使用appendTo(StringBuilder,Iterator)方法
return this.appendTo((StringBuilder)(new StringBuilder()), (Iterator)parts).toString();
}
分析appendTo(StringBuilder, Iterator)的源码
public final StringBuilder appendTo(StringBuilder builder, Iterator<?> parts) {
try {
//调用了appendTo(A, Iterator)方法
this.appendTo((Appendable)builder, (Iterator)parts);
return builder;
} catch (IOException var4) {
throw new AssertionError(var4);
}
}
继续分析<A extends Appendable> A appendTo(A, Interator)方法
public <A extends Appendable> A appendTo(A appendable, Iterator<?> parts) throws IOException {
Preconditions.checkNotNull(appendable);
if(parts.hasNext()) {
//如果第一个迭代器存在,将其添加到出传入的StringBuilder中
appendable.append(this.toString(parts.next()));
//从第二个迭代器开始就会循环方式就会发生变化,每个元素前都会添加规定的分隔符
while(parts.hasNext()) {
appendable.append(this.separator);
appendable.append(this.toString(parts.next()));
}
}
return appendable;
}
useForNull方法
将传入的字符串代替集合中的null输出
源码解析:
public Joiner useForNull(final String nullText) {
Preconditions.checkNotNull(nullText);
// 返回一个Joiner重写了toString方法,将null的参数由nullText代替。
return new Joiner(this, null) {
CharSequence toString(@Nullable Object part) {
return (CharSequence)(part == null?nullText:Joiner.this.toString(part));
}
public Joiner useForNull(String nullTextx) {
throw new UnsupportedOperationException("already specified useForNull");
}
public Joiner skipNulls() {
throw new UnsupportedOperationException("already specified useForNull");
}
};
}
使用 useForNull方法后由于重写了useForNull和skipNulls方法,并且在两个方法中都抛出了异常。所以不能再次调用这两个方法。
skipNulls方法
自动跳过null元素进行拼接
源码解析:
public Joiner skipNulls() {
//返回一个Joiner,重写了 appendTo方法,讲null元素无视掉
return new Joiner(this, null) {
public <A extends Appendable> A appendTo(A appendable, Iterator<?> parts) throws IOException {
Preconditions.checkNotNull(appendable, "appendable");
Preconditions.checkNotNull(parts, "parts");
Object part;
while(parts.hasNext()) {
part = parts.next();
if(part != null) {
appendable.append(Joiner.this.toString(part));
break;
}
}
while(parts.hasNext()) {
part = parts.next();
if(part != null) {
appendable.append(Joiner.this.separator);
appendable.append(Joiner.this.toString(part));
}
}
return appendable;
}
public Joiner useForNull(String nullText) {
throw new UnsupportedOperationException("already specified skipNulls");
}
public Joiner.MapJoiner withKeyValueSeparator(String kvs) {
throw new UnsupportedOperationException("can\'t use .skipNulls() with maps");
}
};
}
使用 skipNulls方法后由于重写了useForNull和skipNulls方法,并且在两个方法中都抛出了异常。所以不能再次调用这两个方法。
对Map解析的函数和类
public Joiner.MapJoiner withKeyValueSeparator(String keyValueSeparator) {
return new Joiner.MapJoiner(this, keyValueSeparator, null);
}
可以看到这个函数返回的是Joiner中的一个内部类,这个类里的大多方法都是在处理Map连接的函数
MapJoiner中的join方法实际上是对Map的entrySet即可以的集合进行拼接