Guava Predicate

1. 简介

Predicate<泛型>(断言,断定),是Guava中的一个基础接口,其内部只有一个方法boolean apply(T input),这个方法输入是一个泛型对象,输出是一个布尔值,非常简单,下面来看一下这个小东西能帮助我们做什么。

2. 使用

2.1 更简单的过滤

在日常开发中,可能有这种需求,当集合中的某些元素不符合条件时,想要过滤掉这些元素,这时我们通常有两种做法。 方法一:

List<Integer> intList = Lists.newArrayList(1, 2, 3, 5, 6);
Iterator<Integer> it = intList.iterator();
while (it.hasNext()) {
    Integer value = it.next();
    if (value == 3 || value == 5) {
        it.remove();
    }
}
System.out.println(intList);

方法二:

List<Integer> intList = Lists.newArrayList(1, 2, 3, 5, 6);
List<Integer> resultList = Lists.newArrayList();
for (Integer value : intList) {
    if (value != 3 && value != 5) {
        resultList.add(value);
    }
}
System.out.println(resultList);

方法一是在原集合上直接做删除操作,我们知道ArrayList实际上就是数组,而数组是连续的内存空间,当删除元素时,后面的元素都需要向前移动,当这个集合很大的时候,就会涉及到大量的移动。方法二是直接新建一个集合,将符合条件的元素添加至新集合中,这样避免了方法一的问题,但这样的写法有一点啰嗦,可以变成下面这样。

List<Integer> intList = Lists.newArrayList(1, 2, 3, 5, 6);
Predicate<Integer> predicate = new Predicate<Integer>() {
    public boolean apply(Integer value) {
        return value != 3 && value != 5;
    }
};
List<Integer> resultList = Lists.newArrayList(Iterables.filter(intList, predicate));
System.out.println(resultList);

将过滤规则抽到Predicate中,如果过滤规则发生变化时,只需修改Predicate即可。

2.2 更优雅的判断

举一个判断稍微复杂的例子,MBA的报考条件是: a) 具有国家承认的大学本科毕业学历后,有三年或三年以上工作经历者。 b) 已获硕士、博士学位,并有两年或两年以上工作经历者。 c) 获得国家承认的大专毕业学历后,有五年或五年以上工作经历。 这时需要一个方法去判断一个考生是否准许考试,方法如下:

private boolean canExam(Examinee examinee) {
    return ("大专".equals(examinee.getEducation()) && examinee.getExperience() >= 5)
            || ("本科".equals(examinee.getEducation()) && examinee.getExperience() >= 3)
            || ("研究生".equals(examinee.getEducation()) && examinee.getExperience() >= 2);
}

当我们去阅读这段代码的时候,只会感觉到一个字,乱,这时可以使用Predicate去改造。首先,将每个条件分支都抽到一个Predicate中。

private Predicate<Examinee> juniorCollege = new Predicate<Examinee>() {
    public boolean apply(Examinee examinee) {
        return "大专".equals(examinee.getEducation()) && examinee.getExperience() >= 5;
    }
};

private Predicate<Examinee> undergraduate = new Predicate<Examinee>() {
    public boolean apply(Examinee examinee) {
        return "本科".equals(examinee.getEducation()) && examinee.getExperience() >= 3;
    }
};

private Predicate<Examinee> postgraduate = new Predicate<Examinee>() {
    public boolean apply(Examinee examinee) {
        return "研究生".equals(examinee.getEducation()) && examinee.getExperience() >= 2;
    }
};

然后,使用Predicates工具将这三个Predicate用or聚合起来,调用其apply方法。

private boolean canExam(Examinee examinee) {
    return Predicates.or(juniorCollege, undergraduate, postgraduate).apply(examinee);
}

canExam变得非常简洁。

2.3 更动态的配置

根据分数返回对这个分数的评级,要求如下: 及格:[60, 70) 良好:[70, 80) 优秀:[80, 100] 可以看到,这是一个分数规则和评级的映射,分数规则是个区间(也可能更复杂),而不是一个具体的值,这时,可以使用Predicate作为key,得到一个评级的配置表。

private Map<Predicate<Double>, String> config = Maps.newHashMap();
{
    config.put(new Predicate<Double>() {
        @Override
        public boolean apply(Double score) {
            return score >= 60 && score < 70;
        }
    }, "及格");
    config.put(new Predicate<Double>() {
        @Override
        public boolean apply(Double score) {
            return score >= 70 && score < 80;
        }
    }, "良好");
    config.put(new Predicate<Double>() {
        public boolean apply(Double score) {
            return score >= 80;
        }
    }, "优秀");
}

然后写一个方法,遍历这个配置,取到符合条件的值,这段代码是统一的。

private String getLevel(Double score) {
    for (Map.Entry<Predicate<Double>, String> entry : config.entrySet()) {
        if (entry.getKey().apply(score)) {
            return entry.getValue();
        }
    }
    return "未知";
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏码匠的流水账

聊聊sentinel的SimpleHttpCommandCenter

sentinel-transport-simple-http-0.1.1-sources.jar!/com/alibaba/csp/sentinel/trans...

441
来自专栏向治洪

listview动态获取数据

1.主Activity 1 public class MainActivity extends Activity { 2 3 private ...

1949
来自专栏码匠的流水账

聊聊spring cloud gateway的GlobalFilter

本文主要研究一下spring cloud gateway的GlobalFilter

701
来自专栏炉边夜话

很幽默的讲解六种Socket I/O模型

信息来源:幻影论坛     作  者: flyinwuhan (制怒·三思而后行)

811
来自专栏函数式编程语言及工具

SDP(9):MongoDB-Scala - data access and modeling

    MongoDB是一种文件型数据库,对数据格式没有硬性要求,所以可以实现灵活多变的数据存储和读取。MongoDB又是一种分布式数据库,与传统关系数据库不同...

3344
来自专栏Python爱好者

Python高效编程(四)

1276
来自专栏施炯的IoT开发专栏

移动物联网 之 家电节能 (2)

    本系列文章结合时下正热的“物联网”概念,介绍实现“家电节能”的一套解决方案。本部分讲述 “家电节能”的具体实现方法。 1. 系统结构 系统包括Senso...

1817
来自专栏领域驱动设计DDD实战进阶

DDD实战进阶第一波(七):开发一般业务的大健康行业直销系统(实现产品上下文接口与测试)

前一篇文章我们介绍了如何将创建产品的领域逻辑与产品的持久化仓储通过上架产品的用例组织起来,完成了一个功能。在实际的项目中,多种前端的形态比如PC Web、 微信...

3415
来自专栏个人随笔

C#编写影院售票系统(A project with a higher amount of gold )(2:相关代码)

此篇文章为项目代码,,,需要项目需求 ,思路分析与窗体效果请访问:http://www.cnblogs.com/lsy131479/p/8367304.html...

2625
来自专栏吴小龙同學

Android Retrofit 2.0 使用-补充篇

推荐阅读,猛戳: 1、Android MVP 实例 2、Android Retrofit 2.0使用 3、RxJava 4、RxBus 5、Android MV...

28410

扫码关注云+社区