链接地址:http://www.xx566.com/detail/131.html
在上一篇Guava库学习:函数编程(一)使用Function和Functions进行对象转换中, 我们学习Function和Functions,并使用函数式编程进行对象的处理转换,在Guava中Function有一个双胞胎兄弟 Predicate,如果说Function用于转换,那么Predicate则主要用于对象的过滤和筛选处理,二者的设计上有异曲同工之妙,下面我们开 始进行Predicate和Predicates的学习。
翻开Predicate的源码,我们看到,与Function接口类似,其中也只包含两个方法,我们只介绍其中的apply()方法,其接收参数对象,返 回过滤后是否符合条件的boolean值,当接收的参数为null时,会抛出NullPointerException异常。
Predicate与Function有太多相似的设计,学习起来难度并不大,下面,通过一个例子来进行Predicate的学习,首先假定我要到了要结 婚的年纪,家里人给介绍了一些Girl,年纪啊,相貌啊,我们当然需要过滤这些Girl的年纪是否达到18岁,如下:
static class Girl {
int age;
String face;
Girl(int age, String face) {
this.age = age;
this.face = face;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getFace() {
return face;
}
public void setFace(String face) {
this.face = face;
}
}
@Test
public void testPredicate() {
Predicate predicate = new Predicate() {
@Override
public boolean apply(Girl input) {
return input.getAge() >= 18;
}
};
//有个18岁的漂亮姑娘
Girl girl = new Girl(18, "nice");
if (predicate.apply(girl)) {
System.out.println("be my girl friend");
} else {
System.out.println("too young to love");
}
//输出结果:be my girl friend
}
与Guava提供Function接口的实现工具类Functions类似,Guava也提供了Predicate接口的实现Predicates,翻开源码,其中提供了大量的实现和一些常用的公共方法,这里简要做一些讲述,如下:
alwaysTrue():返回预估结果总是为true的Predicate实例。
alwaysFalse():返回预估结果总是为false的Predicate实例。
isNull():返回被测试的对象引用为null的预估为true的Predicate实例。
notNull():返回被测试的对象引用不为null的预估为true的Predicate实例。
not(Predicate<T> predicate):返回传入Predicate预估为false的预估结果为true的Predicate实例。
and(Predicate<? super T> first,Predicate<? super T> second):返回传入的两个Predicate预估都为true的预估结果为true的Predicate实例,重载的方法有 Predicates.and(Iterable<Predicate<T>> predicates),Predicates.and(Predicate<T> ...predicates),作用与之相同。
or(Predicate<? super T> first,Predicate<? super T> second):返回传入的两个Predicate任何一个预估为true的预估结果为true的Predicate实例,重载的方法有 Predicates.or(Iterable<Predicate<T>> predicates),Predicates.or(Predicate<T> ...predicates),作用与之相同。
equalTo(@Nullable T target):返回当传入对象与被测试对象相同或传入对象为空时预估结果为true的Predicate实例。
instanceOf(Class<?> clazz):返回当被测试对象是传入class的实例时预估结果为true的Predicate实例。
assignableFrom(Class<?> clazz):返回被测试的对象确定为传入的class时预估结果为true的Predicate实例。
in(Collection<? extends T> target):返回当被测试的对象存在于传入的集合时预估结果为true的Predicate实例。
compose(Predicate<B> predicate, Function<A, ? extends B> function):返回Function和Predicate的组合。
containsPattern(String pattern):返回当被测试字符串包含任何能够匹配传入正则表达式的字符时预估为true的Predicate实例。
contains(Pattern pattern):返回当被测试字符串包含任何能够匹配传入正则表达式模式的字符时预估为true的Predicate实例。
接下来,我们通过下面的代码来加深对Predicate与Predicates的学习和理解代码如下:
@Test
public void testPredicates() {
Predicate<Girl> agePredicate = new Predicate<Girl>() {
@Override
public boolean apply(Girl input) {
return input.getAge() >= 18;
}
};
Predicate<Girl> facePredicate = new Predicate<Girl>() {
@Override
public boolean apply(Girl input) {
return input.getFace().equals("nice");
}
};
Girl girl = new Girl(18, "ugly");
//and:用于过滤两个Predicate都为true
Predicate<Girl> predicate = Predicates.and(agePredicate, facePredicate);
checkOut(predicate.apply(girl)); //输出结果:She doesn't fit me
//or:用于过滤其中一个Predicate为true
predicate = Predicates.or(agePredicate, facePredicate);
checkOut(predicate.apply(girl)); //输出结果:She fits me
//or:用于将指定Predicate取反
Predicate<Girl> noneAgePredicate = Predicates.not(agePredicate);
predicate = Predicates.and(noneAgePredicate, facePredicate);
checkOut(predicate.apply(girl)); //输出结果:She doesn't fit me
//compose: Function与Predicate的组合
Map<String, Girl> map = new HashMap<String, Girl>() {
//构造一个测试用Map集合
{
put("love", new Girl(18, "nice"));
put("miss", new Girl(16, "ugly"));
}
};
Predicate<Girl> predicate1 = Predicates.and(agePredicate, facePredicate);
Function<String, Girl> function1 = Functions.forMap(map);
Predicate<String> stringPredicate = Predicates.compose(predicate1, function1);
System.out.println(stringPredicate.apply("love"));//true
System.out.println(stringPredicate.apply("miss"));//false
}
/**
* 判断输出
*
* @param flag
*/
private void checkOut(boolean flag) {
if (flag) {
System.out.println("She fits me");
} else {
System.out.println("She doesn't fit me");
}
}
总结:Predicate的学习与Function类似,其中的一些方法的作用也是直接来自于对源码注释的翻译,难免有不足,造成难以理解或者误解,具体的Predicate的更多运用可能随着Guava的不断学习,才能做到深入和透彻的理解吧。