这个定义了一系列的算法,并将每个算法封装起来,使它们还可以相互替换。策略模式让算法的变化不会影响到使用算法的客户,在Splitter中就主要使用了这种模式。
1、首先看一个内部类
这个类才是真正去处理字符、字符串、正则表达式的接口,这个接口的定义其实就是策略模式。此接口中只有一个方法,返回的是一个Iterator迭代器,这里我们可以先联想到最终返回的集合的迭代器会和它有关系。
2、 这是一个实现AbstractIterator的一个抽象类,它实现了 computeNext方法,这个方法实际上是规定了此迭代器的一个迭代规则。所以Splitter类为他分割完的结果集也写了一个迭代器并规定了自己的迭代规则。从这个迭代器的实现上,在结合Strategy 类便可以将整个字符串分割的过程给串起来了。
这里实现了一个惰性迭代器,直到不得不计算的时候才会去将字符串分割,也就是说迭代的时候才去分割字符串,无论将分隔符还是被分割的字符串加载到Splitter类中,都不会去分割,只有在迭代的时候才会真正的去分割。
这个方法太长我就不全部截图了,我写在了一个文本里,链接如下:
部分源码.class
3、变量部分
//移除指定字符项,即集合中当前元素与trimmer匹配,将其移除。如果没有设置trimmer,则将结果中的空格删除
//最终结论为:将结果集中的每个字符串前缀和后缀都去除trimmer,知道前缀或后缀没有这个字符了,字符串“中”的不用去除
private final CharMatcher trimmer;
//是否移除结果集中的空集,true为移除结果集中的空集,false为不用移除结果集中的空集
private final boolean omitEmptyStrings;
//这个变量最终会返回一个所有集合类的父接口,它是贯穿着整个字符串分解的变量
private final Splitter.Strategy strategy;
//最多将字符串分为几个集合,比如limit=3, 对”a,b,c,d”字符串进行','分割,返回的[”a”,”b”,”c,d”] 意思为最多可以分割成3段,这个可以在链式编程的limit方法参数设置
private final int limit;
4、构造函数
这两个构造函数都是静态构造器,所以不能直接使用这两个构造器去创建Splitter,想要创建Splitter可以使用静态方法。
静态创建Splitter函数可以按照4类进行分析(接收字符、字符串、正则表达式的和按指定长度分割构造器):
(1)接收字符的构造函数
//接收一个字符的构造器,然后调用参数为 CharMatcher的构造器
public static Splitter on(char separator) {
return on((CharMatcher)CharMatcher.is(separator));
}
//接收一个CharMatcher的构造器
public static Splitter on(final CharMatcher separatorMatcher) {
//对字符判空
Preconditions.checkNotNull(separatorMatcher);
//返回一个Splitter对象,传入Strategy对象,并对Strategy接口进行实现
return new Splitter(new Splitter.Strategy() {
//实现接口Strategy的iterator方法
public Splitter.SplittingIterator iterator(final Splitter splitter, final CharSequence toSplit) {
//返回 SplittingIterator对象,并对 SplittingIterator 抽象类实现 separatorStart方法和 separatorEnd方法
return new Splitter.SplittingIterator(splitter, toSplit) {
//返回从start开始的第一个分隔符的开始位置
int separatorStart(int start) {
return separatorMatcher.indexIn(this.toSplit, start);
}
//返回当前分割符的末尾位置
int separatorEnd(int separatorPosition) {
return separatorPosition + 1;
}
};
}
});
}
(2)接收字符串的构造函数
//传入一个字符串作为分隔符
public static Splitter on(final String separator) {
Preconditions.checkArgument(separator.length() != 0, "The separator may not be the empty string.");
//如果当前字符串的长度为1,则直接调用解析单个字符的构造器上,否则会返回一个Splitter对象,传入Strategy对象,并对Strategy接口进行实现
return separator.length() == 1?on(separator.charAt(0)):new Splitter(new Splitter.Strategy() {
//实现Strategy接口
public Splitter.SplittingIterator iterator(final Splitter splitter, final CharSequence toSplit) {
return new Splitter.SplittingIterator(splitter, toSplit) {
//这个方法是被分割字符串从start开始,找到第一个分隔符然后返回位置,没有找到返回-1
public int separatorStart(int start) {
//获取分割符长度
int separatorLength = separator.length();
//记录分割符开始位子
int p = start;
//调用本类的 toSplit 变量即被分割的字符串长度,last取被分割的字符串长度与分割符的差值
//分割符号”,” 被分割字符串”a,b,c,d” last= 7-1 = 6
int last = this.toSplit.length() - separatorLength;
//找到匹配到分隔符的第一个位置
label23:
while(p <= last) {
for(int i = 0; i < separatorLength; ++i) {
if(this.toSplit.charAt(i + p) != separator.charAt(i)) {
++p;
continue label23;
}
}
return p;
}
return -1;
}
//传入分离器位置,返回分离器末尾位置
public int separatorEnd(int separatorPosition) {
return separatorPosition + separator.length();
}
};
}
});
}
(3)接收正则表达式的构造函数
//传入一个字符串,返回一个调用传入CommonPattern类型的on方法
@GwtIncompatible
public static Splitter onPattern(String separatorPattern) {
return on((CommonPattern)Platform.compilePattern(separatorPattern));
}
//传入一个Pattern类型参数,返回一个调用传入CommonPattern类型的on方法
@GwtIncompatible
public static Splitter on(Pattern separatorPattern) {
return on((CommonPattern)(new JdkPattern(separatorPattern)));
}
//传入一个 CommonPattern类型的构造器
private static Splitter on(final CommonPattern separatorPattern) {
Preconditions.checkArgument(!separatorPattern.matcher("").matches(), "The pattern may not match the empty string: %s", separatorPattern);
//返回一个Splitter对象,传入Strategy对象,并对Strategy接口进行实现
return new Splitter(new Splitter.Strategy() {
//实现Strategy对象的iterator方法
public Splitter.SplittingIterator iterator(final Splitter splitter, final CharSequence toSplit) {
final CommonMatcher matcher = separatorPattern.matcher(toSplit);
return new Splitter.SplittingIterator(splitter, toSplit) {
//返回从start开始的第一个分隔符的开始位置
public int separatorStart(int start) {
return matcher.find(start)?matcher.start():-1;
}
//返回当前分割符的末尾位置
public int separatorEnd(int separatorPosition) {
return matcher.end();
}
};
}
});
}
(4)按照指定长度进行分割的构造函数
public static Splitter fixedLength(final int length) {
Preconditions.checkArgument(length > 0, "The length may not be less than 1");
return new Splitter(new Splitter.Strategy() {
public Splitter.SplittingIterator iterator(final Splitter splitter, final CharSequence toSplit) {
return new Splitter.SplittingIterator(splitter, toSplit) {
//按 length长度进行跨步
public int separatorStart(int start) {
int nextChunkStart = start + length;
return nextChunkStart < this.toSplit.length()?nextChunkStart:-1;
}
public int separatorEnd(int separatorPosition) {
return separatorPosition;
}
};
}
});
}
5、进行分割的函数 (split、splittingIterator)
这个有两个返回值:容器、List
(1)返回值为容器的
public Iterable
Preconditions.checkNotNull(sequence);
//返回一个容器,然后重写了iterator和toString方法
return new Iterable() {
public Iterator
//调用了 splittingIterator方法,以下可以查看 splittingIterator方法的实现
return Splitter.this.splittingIterator(sequence);
}
public String toString() {
return Joiner.on(", ").appendTo((new StringBuilder()).append('['), this).append(']').toString();
}
};
}
这个是 splittingIterator的源码
private Iterator
return this.strategy.iterator(this, sequence);
}
调用了Strategy的iterator方法,这个方法在on里面有多种的实现方法,所以结合最先的 SplittingIterator类重写的迭代方法,这里就形成了一个特殊的容器返回,真正的拆分字符串动作是在迭代的时候进行的。
(2)返回值为List
这和上面一样调用了Strategy和SplittingIterator中的方法实现了在迭代时候去分割字符串,只不过它在真正的迭代了一遍然后将结果集放在了List容器中。
就先写这么多吧 ,后面有什么想法了再写。