博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java8-谓词(predicate)
阅读量:6591 次
发布时间:2019-06-24

本文共 4168 字,大约阅读时间需要 13 分钟。

传递代码

我们首先看一个例子,假设你有一个 Apple 类,它有一个getColor方法,还有一个变量inventory保存着一个Apples的列表。你可能想要选出所有的绿苹果,并返回一个列表。通常我们用筛选(filter)一词来表达这个概念。在Java 8之前,你可能会写这样一个方法 filterGreenApples :

public static List
filterGreenApples(List
inventory){List
result = new ArrayList<>();for (Apple apple: inventory){if ("green".equals(apple.getColor())) {result.add(apple); } }return result;}

但是接下来,有人可能想要选出重的苹果,比如超过150克,于是你心情沉重地写了下面这

个方法,甚至用了复制粘贴:

public static List
filterHeavyApples(List
inventory){List
result = new ArrayList<>();for (Apple apple: inventory){if (apple.getWeight() > 150) {result.add(apple); } }return result;}

我们都知道软件工程中复制粘贴的危险——给一个做了更新和修正,却忘了另一个。嘿,这

两个方法只有一行不同: if 里面高亮的那行条件。如果这两个高亮的方法之间的差异仅仅是接受
的重量范围不同,那么你只要把接受的重量上下限作为参数传递给 filter 就行了,比如指定
(150, 1000) 来选出重的苹果(超过150克),或者指定 (0, 80) 来选出轻的苹果(低于80克)。
但是,我们前面提过了,Java 8会把条件代码作为参数传递进去,这样可以避免 filter 方法
出现重复的代码。现在你可以写:

public static boolean isGreenApple(Apple apple) {    return "green".equals(apple.getColor());}public static boolean isHeavyApple(Apple apple) {    return apple.getWeight() > 150;}static List
filterApples(List
inventory, Predicate
p) { List
result = new ArrayList<>(); for (Apple apple: inventory){ if (p.test(apple)) { result.add(apple); } } return result;}

要用它的话,你可以写:

filterApples(inventory, Apple::isGreenApple);
或者
filterApples(inventory, Apple::isHeavyApple);
什么是谓词?

前面的代码传递了方法 Apple::isGreenApple (它接受参数 Apple 并返回一个
boolean )给 filterApples ,后者则希望接受一个 Predicate<Apple> 参数。词 谓词(predicate)
在数学上常常用来代表一个类似函数的东西,它接受一个参数值,并返回 true 或 false 。你
在后面会看到,Java 8也会允许你写 Function<Apple,Boolean> ——在学校学过函数却没学
过谓词的读者对此可能更熟悉,但用 Predicate<Apple> 是更标准的方式,效率也会更高一
点儿,这避免了把 boolean 封装在 Boolean 里面。
从传递方法到 Lambda

把方法作为值来传递显然很有用,但要是为类似于 isHeavyApple 和 isGreenApple 这种可

能只用一两次的短方法写一堆定义有点儿烦人。不过Java 8也解决了这个问题,它引入了一套新
记法(匿名函数或Lambda),让你可以写
filterApples(inventory, (Apple a) -> "green".equals(a.getColor()) );
或者
filterApples(inventory, (Apple a) -> a.getWeight() > 150 );
甚至
filterApples(inventory, (Apple a) -> a.getWeight() < 80 ||
"brown".equals(a.getColor()) );
完整的代码为:

public class FilteringApples1 {    public static void main(String[] args) {        List
inventory = Arrays.asList(new FilteringApples1.Apple(80, "green"), new FilteringApples1.Apple(155, "green"), new FilteringApples1.Apple(120, "red")); List
greenApples2 = filterApples(inventory, (FilteringApples1.Apple a) -> "green".equals(a.getColor())); System.out.println(greenApples2); // [Apple{color='green', weight=155}] List
heavyApples2 = filterApples(inventory, (FilteringApples1.Apple a) -> a.getWeight() > 150); System.out.println(heavyApples2); // [] List
weirdApples = filterApples(inventory, (FilteringApples1.Apple a) -> a.getWeight() < 80 || "brown".equals(a.getColor())); System.out.println(weirdApples); } public static List
filterApples(List
inventory, Predicate
p) { List
result = new ArrayList<>(); for (FilteringApples1.Apple apple : inventory) { if (p.test(apple)) { result.add(apple); } } return result; } public static class Apple { private int weight = 0; private String color = ""; public Apple(int weight, String color) { this.weight = weight; this.color = color; } public Integer getWeight() { return weight; } public void setWeight(Integer weight) { this.weight = weight; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public String toString() { return "Apple{" + "color='" + color + '\'' + ", weight=" + weight + '}'; } }}

java8中内置filter函数

static 
Collection
filter(Collection
c, Predicate
p);

这样你甚至都不需要写 filterApples 了,因为比如先前的调用

filterApples(inventory, (Apple a) -> a.getWeight() > 150 );

就可以直接调用库方法 filter :

filter(inventory, (Apple a) -> a.getWeight() > 150 );

转载地址:http://mhkio.baihongyu.com/

你可能感兴趣的文章
windows网络安全以及常见网络***方式
查看>>
警告 初始化默认驱动器时出错“找不到运行 Active Directory Web 服务的默认服务器。”...
查看>>
JS字符串转换数字
查看>>
centos7-修改主机名
查看>>
面试宝典系列-mysql面试基础题
查看>>
微信硬件平台对接--蓝牙
查看>>
spring data for mongo
查看>>
开启 URL 重写
查看>>
Journey源码分析二:整体启动流程
查看>>
Shell特殊变量:Shell $0, $#, $*, $@, $?, $$和命令行参数
查看>>
七、MySQL中的字符集 - 系统的撸一遍MySQL
查看>>
centos7的php5.4竟然不支持原生的mysql
查看>>
使用IntelliJ IDEA开发SpringMVC网站(四)用户管理
查看>>
Maven依赖Scope标签用法
查看>>
ajax加载数据到页面无法打印的解决办法
查看>>
js 验证中文
查看>>
MySQL给查询结果添加一表表示行号或名次(1)
查看>>
Linux下运行java DES AES加解密
查看>>
DataNode 运行状况
查看>>
牛津词典 2018 年度词汇 ——「有毒」!
查看>>