Guava优美代码-13-Predicate

Guava函数式编程

上一节篇文章我们说了Guava的Function函数的用法,这一节我们来说一说Predicate预言。Predicate的使用也是非常多的,因此读者朋友们也需要多多重视Predicate的用法。简单说一下PredicateFunction的区别,你可以理解为Predicate主要是用来判断一些条件成不成立的,而Function主要是用来执行一些操作的,侧重点不同。

Predicate和Predicates

Predicate<T>,它声明了单个方法boolean apply(T input)。Predicate对象通常也被预期为无副作用函数,并且”相等”语义与equals一致。

同样我们说Predicates提供了更多构造和处理Predicate的方法,下面是一些例子:

方法名 方法名 方法名
instanceOf(Class) assignableFrom(Class) contains(Pattern)
in(Collection) isNull() alwaysFalse()
alwaysTrue() equalTo(Object) compose(Predicate, Function)
and(Predicate…) or(Predicate…) not(Predicate)

Predicate使用案例

和前一节的国家-首都的例子一样,我们使用相同的数据来说明。这里我们还是列出他们的源码,方便大家阅读。

CountryEnum.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package com.qinjiangbo.vo;

import com.google.common.collect.Lists;

import java.util.List;

/**
* Date: 9/4/16
* Author: [email protected]
*/
public enum CountryEnum {
CHINA("CHINA", "BEIJING", 2000, "ASIA"),
US("US", "WASHINGTON DC", 200, "AMERICA"),
KOREA("KOREA", "SEUL", 500, "ASIA"),
GB("GB", "LONDON", 1000, "EURO"),
FINLAND("FINLAND", "", 1000, "EURO");

private String name;
private String capital;
private int age;
private String continent;

private CountryEnum(String name, String capital, int age, String continent) {
this.name = name;
this.capital = capital;
this.age = age;
this.continent = continent;
}

public static List<CountryEnum> findCountries() {
return Lists.newArrayList(CHINA, US, KOREA, FINLAND, GB);
}

public String getContinent() {
return continent;
}

public void setContinent(String continent) {
this.continent = continent;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getCapital() {
return capital;
}

public void setCapital(String capital) {
this.capital = capital;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

}

同样地,我们对国家-首都关系数据作出如下的判断:

(1) 判断列表中的国家是否定义了首都

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
public void testHasCapitalDefined() {
Predicate<CountryEnum> capitalCityProvidedPredicate = new Predicate<CountryEnum>() {
@Override
public boolean apply(@Nullable CountryEnum country) {
return !Strings.isNullOrEmpty(country.getCapital());
}
};

boolean allCountriesSpecifyCapital = Iterables.all(
Lists.newArrayList(CountryEnum.CHINA, CountryEnum.GB, CountryEnum.FINLAND), capitalCityProvidedPredicate
);

System.out.println(allCountriesSpecifyCapital); // false
}

上面这个结果是false,因为我们可以看到,上面的枚举类中FINLAND的首都是没有定义的,为空,所以这个预言的结果是false

(2) 复合预言Composed Predicate

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Test
public void testComposedPredicate() {
Predicate<CountryEnum> fromAsiaPredicate = new Predicate<CountryEnum>() {
@Override
public boolean apply(@Nullable CountryEnum country) {
return country.getContinent().equals("ASIA");
}
};

Predicate<CountryEnum> historyPredicate = new Predicate<CountryEnum>() {
@Override
public boolean apply(@Nullable CountryEnum country) {
return country.getAge() > 1000;
}
};

Predicate<CountryEnum> composedPredicate = Predicates.and(fromAsiaPredicate, historyPredicate);

Iterable<CountryEnum> filteredCountries = Iterables.filter(CountryEnum.findCountries(), composedPredicate);

Iterator iterator = filteredCountries.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
// CHINA
}

输出的结果是CHINA,因为从数据来看,只有中国既是亚洲国家,历史也超过了1000年。所以她是唯一合格的选项。

(3) 预言包含关系

1
2
3
4
5
6
@Test
public void testContainsPredicate() {
Predicate<CharSequence> containsPredicate = Predicates.containsPattern("\\d\\d");
boolean isContained = containsPredicate.apply("hello world 21!");
System.out.println(isContained); // true
}

这个例子和上面的国家-首都数据无关了,纯粹是一个功能点的说明,这里我们需要判断一个句子中是否包含我们需要检测的字符串。这里我们使用了正则表达式\\d\\d,表示匹配连续的两个数字,hello world 21!中有21,所以这段代码结果是true

总结

简单总结一下,这篇博文里面知识简单地为大家介绍了Predicate类中的一些方法,其实Predicate类中还有很多实用的方法,大家可以自己调用Guava的相关方法好好体会。看的再多,不如自己动手敲一波!

分享到