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 条评论
登录 后参与评论

相关文章

来自专栏PHP在线

数据类型和Json格式

作者: 阮一峰 1. 前几天,我才知道有一种简化的数据交换格式,叫做yaml。 我翻了一遍它的文档,看懂的地方不多,但是有一句话令我茅塞顿开。 它说,从结构上看...

33810
来自专栏程序人生

来来来,咱们元编程入个门

前一篇文章竟然被很多人批「干货太少」 —— 一看你们就没有看过 Rich 他老人家的 Hammock Driven Development(我很久前推荐过滴),...

31910
来自专栏Crossin的编程教室

【Python 第50课】 面向对象(4)

上一课举了一个面向对象和面向过程相比较的例子之后,有些同学表示,仍然没太看出面向对象的优势。没关系,那是因为我们现在接触的程序还不够复杂,等以后你写的程序越来越...

2766
来自专栏iKcamp

翻译连载 | 附录 A:Transducing(上)-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇

原文地址:Functional-Light-JS 原文作者:Kyle Simpson-《You-Dont-Know-JS》作者 JavaScript 轻量级函数...

1898
来自专栏Python小屋

Python中带else子句的for循环执行过程

这几天在厦门讲课,每天6小时,没有太多时间写新代码,宾馆不知道咋想的也不提供WiFi,只好用手机做个热点临时分享一点基础知识,300M的包月流量伤不起,热点瞬间...

2544
来自专栏Java技术栈

刚写完排序算法,就被开除了…

据说是一个月薪 9K 的 Java 程序员,因老板让他写一个排序算法,然后他就写了一段屌炸天的休眠排序算法,接着他就被老板开除了……

432
来自专栏程序员与猫

使用抽象类和接口的优解

761
来自专栏互联网技术栈

设计模式-组合模式(Composite)

定义 将对象以树形结构组织起来,以达成“部分-整体” 的层次结构,使得客户端对单个对象和组合对象的使用具有一致性.

565
来自专栏工科狗和生物喵

【计算机本科补全计划】指令:计算机的语言(MIPS) Part4

正文之前 这几天陪人玩去了,所以没怎么看书。今早某人回家了。所以我也就可以一个人继续开始在图书馆的浪荡之路了。爽歪歪!!!!而且可以一个人独占温暖的地方,实在...

3456
来自专栏编程一生

专治不会看源码的毛病--spring源码解析AOP篇

1225

扫码关注云+社区