这写API可解决的问题
1. 集合元素的过滤 - FluentIterable Predicate Range Function
1) 先说Predicate<T>,这个相当与一个过滤原则,里面有个apply()方法,通过一定的条件返回true或false,依次判断元素需不需要过滤
其中T表示待过滤集合里面的元素类型,举个例子
package guavaexam.test; public class Man { private String name; private int age; public Man(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } @Override public String toString() { return name + " is " + age + " years old"; } } package guavaexam.test; import com.google.common.base.Predicate; public class AgePredicate implements Predicate<Man> { private int minAge; public AgePredicate(int minAge) { this.minAge = minAge; } @Override public boolean apply(Man man) { if (man.getAge() < minAge) return false; return true; } } package guavaexam.test; import com.google.common.base.Predicate; public class NamePredicate implements Predicate<Man> { private String illegalName; public NamePredicate(String illegalName) { this.illegalName = illegalName; } @Override public boolean apply(Man man) { if (man.getName().contains(illegalName)) return false; return true; } }
此处predicate的作用是用来过滤age小于minAge的人,运用Predicates.and(predicate1, predicate2)或者Predicates.or(x,x)方法,我们可以组合多个predicate过滤器,形成一个复杂的组合条件来过滤集合元素
2) 再来说Function<E, T>,这个类主要使用来转换集合元素,其中有个apply方法,将 E 类型的元素转为 T 类型的元素返回,一般我们可以写在一个匿名类里用,例如
Iterable<Man> manIterable = FluentIterable.from(manList).filter(predicate).limit(2) .transform(new Function<Man, Man>() { @Override public Man apply(Man man) { man.setAge(man.getAge() * 2); return man; } });
这个例子表示的就是将集合里的每个Man的年龄乘以2再返回
3) FluentIterable,这个类可以配合Predicate和Function对集合的每个元素进行自定义过滤,他们的配合就类似与Collections.sort()和Comparator的组合,查看如下完整的例子
package guavaexam.test; import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableList; import java.util.List; public class FluentIterableTest { public static void main(String[] args) { Man man1 = new Man("Jack Miller", 18); Man man2 = new Man("Roy Miller", 18); Man man3 = new Man("Lily Miller", 11); Man man4 = new Man("Rose Miller", 5); Man man5 = new Man("Mike Chen", 34); List<Man> manList = ImmutableList.of(man1, man2, man3, man4, man5); // 组合Predicate条件 Predicate<Man> predicate = Predicates.alwaysTrue(); predicate = Predicates.and(predicate, new NamePredicate("Chen")); predicate = Predicates.and(predicate, new AgePredicate(15)); // 使用FluentIterable过滤元素,返回一个Iterable[] Iterable<Man> manIterable = FluentIterable.from(manList).filter(predicate).limit(2) .transform(new Function<Man, Man>() { @Override public Man apply(Man man) { man.setAge(man.getAge() * 2); return man; } }); System.out.println(manIterable); } }
结果输出
[Jack Miller is 36 years old, Roy Miller is 36 years old]
2. 集合元素的排序
Ordering类用来构建复杂比较器,其中几个方法如下:
from(): 第一个使用的比较器,第一顺序
compound(): 第二个使用的比较器,第二顺序
onResultOf(Function func): 在两个元素比较之前,先用Function转换这个两个元素,注意是在两个元素比较之前,而不是在所有元素比较之前,下面可以看到效果
看下面的例子
package guavaexam.test.ordering; import guavaexam.test.model.Man; import java.util.Comparator; public class NameComparator implements Comparator<Man> { @Override public int compare(Man man, Man man1) { return man.getName().compareTo(man1.getName()); } } package guavaexam.test.ordering; import guavaexam.test.model.Man; import java.util.Comparator; public class AgeComparator implements Comparator<Man> { @Override public int compare(Man man, Man man1) { return man.getAge() > man1.getAge() ? 1 : (man.getAge() == man1.getAge() ? 0 : -1); } } package guavaexam.test.ordering; import com.google.common.base.Function; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import com.google.common.collect.Ordering; import guavaexam.test.model.Man; import java.util.Collections; import java.util.Comparator; import java.util.List; public class OrderingTest { public static void main(String[] args) { Man man1 = new Man("Jack Miller", 18); Man man2 = new Man("Roy Miller", 18); Man man3 = new Man("Lily Miller", 11); Man man4 = new Man("Rose Miller", 5); Man man5 = new Man("Mike Chen", 34); List<Man> manList = Lists.newArrayList(man1, man2, man3, man4, man5); Comparator<Man> manComparator = Ordering .from(new AgeComparator()).compound(new NameComparator()) .reverse() .onResultOf(new Function<Man, Man>() { @Override public Man apply(Man man) { man.setAge(man.getAge() * 2); return man; } }); Collections.sort(manList, manComparator); System.out.println(manList); } }
这个输出会非常诡异
[Roy Miller is 72 years old, Jack Miller is 144 years old, Lily Miller is 176 years old, Mike Chen is 136 years old, Rose Miller is 40 years old]
可以看到年龄并非只是 * 2,而是不可预见的被 * 2 了多次,这是因为当元素A在与元素B比较的时候就会被执行一次Function,当元素A与元素C比较时又会执行一次Function,所以最后你并不知道被执行了多少次
3. 范围判断 - Range
比较简单,不多做介绍了
package guavaexam.test.range; import com.google.common.collect.Range; public class RangeTest { public static void main(String[] args) { // 一个左开右闭的范围 Range<Integer> range = Range.openClosed(5, 10); System.out.println(range.contains(1)); System.out.println(range.contains(6)); System.out.println(range.contains(9)); System.out.println(range.contains(10)); } }
输出
false
true
true
true
4. Splitter 字符串切割
其常用方法有如下几个
on(String sep): 按照sep切分字符串
trimResults(): 去掉切分结果的首尾空格
omitEmptyStrings(): 忽略切分出来的空结果
withKeyValueSeparator(String sep): 根据sep在字符串切割后再切割结果变成一个map
例子如下
package guavaexam.test.splitter; import com.google.common.base.Splitter; import java.util.Map; public class SplitterTest { public static void main(String[] args) { String s = " name $ jack?age$ 17 ? $ook ?"; Iterable<String> list = Splitter.on("?").trimResults().omitEmptyStrings().split(s); System.out.println(list); Map<String, String> list2 = Splitter.on("?").trimResults().omitEmptyStrings().withKeyValueSeparator("$").split(s); System.out.println(list2); } }
[name $ jack, age$ 17, $ook]
{name = jack, age= 17, =ook}