Java8 新特性连载——内置函数式接口之Predicates

Java8引入函数式接口(关于函数式接口,可以戳 ),同时在JDK中也内置了大量非常好用的函数式接口,它们的存在能让你的编码生涯更加轻松。实际上用过Google Guava库的童鞋应该就相当有体会,本文就花一分钟阐述Predicates的用法

一、应用场景描述

在实际项目中,经常会遇到从一个集合中依据某种过滤条件筛选出合适的对象,然后放入一个新的集合中,例如有个猫类:

public class Cat {
private String name;
private Integer type;
private Integer age;
// set get 忽略
}

然后我们有一个猫的集合:

List cats = new ArrayList<>();

现在我们需要根据类别筛选出加菲猫,我们都这么干:

public List getGarfield() {
List garfields = new ArrayList<>();
for(Cat cat:cats) {
if(cat.getType().equals("Garfield")) {
garfields.add(cat);
}
}
return garfields;
}

过了段时间,我们又需要找出年龄大于某个年龄的猫,我们又写了个方法:

public List getCatsByAgeGreatThan(int age) {
List bigcats = new ArrayList<>();
for(Cat cat:cats) {
if(cat.getAge() > 2) {
bigcats.add(cat);
}
}
}

以后可能还会有更多的查询要求出来,但所有这些代码差异及其小,仅仅只是if的条件不一样,然后你写了一堆的查询方法,坑不?

这下好了,Java8的Predicates来拯救你了,用过Google Guava库的童鞋肯定对这个词语不会陌生,这回Java把它内置到JDK了。我们来看看它是如何拯救你的。

二、了解一下Predicates

我们查看java源码不难发现,实际上Predicate就是一个函数接口,它只有一个抽象方法:

boolean test(T t);

还有三个默认实现的方法,分别实现了最常用的逻辑判断:and、or和not

接口就是如此简单,那么怎么用呢?

三、用法详解

之前,我们为了满足需求,写了一堆的查询方法,如果用Predicate,我们只需要一个方法就可以了:

public List query(Predicate predicate) {
List result = new ArrayList<>();
for(Cat cat:cats) {
if(predicate.test(cat)) {
result.add(cat);
}
}
return result;
}

然后我们可以这么查询加菲猫:

List garfields = query(c -> "Garfield".equals(c.getType()));

然后这么查找大于两岁的猫:

List garfields = query(c -> c.getAge() > 2);

我们还可以组合条件,例如查找大于两岁的加菲猫:

Predicate p = (c) -> "Garfield".equals(c.getType());
List garfields = query(p.and(c -> c.getAge() > 2));

真是用过一次就爱上了有木有。

四、进一步了解

上面的阐述是我们为了阐述Predicate用法而展开的解释,实际上对于容器的过滤,Java8已经在内部就已经实现了,我们直接就可以用容器的stream来达到过滤的目的,连query方法都不用写,一句话就搞定了:

List result = cats.stream().filter(c -> c.getAge() > 2).collect(Collectors.toList());

注意其中的filter,filter的参数就是Predicate,哇哦,实在是太方便啦……


分享到:


相關文章: