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