传递代码
我们首先看一个例子,假设你有一个 apple 类,它有一个getcolor方法,还有一个变量inventory保存着一个apples的列表。你可能想要选出所有的绿苹果,并返回一个列表。通常我们用筛选(filter)一词来表达这个概念。在java 8之前,你可能会写这样一个方法 filtergreenapples :
public static list<apple> filtergreenapples(list<apple> inventory){list<apple> result = new arraylist<>();for (apple apple: inventory){if (green.equals(apple.getcolor())) {result.add(apple); } }return result;}
但是接下来,有人可能想要选出重的苹果,比如超过150克,于是你心情沉重地写了下面这
个方法,甚至用了复制粘贴:
public static list<apple> filterheavyapples(list<apple> inventory){list<apple> 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<apple> filterapples(list<apple> inventory, predicate<apple> p) { list<apple> 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<filteringapples1.apple> inventory = arrays.aslist(new filteringapples1.apple(80, green), new filteringapples1.apple(155, green), new filteringapples1.apple(120, red)); list<filteringapples1.apple> greenapples2 = filterapples(inventory, (filteringapples1.apple a) -> green.equals(a.getcolor())); system.out.println(greenapples2); // [apple{color='green', weight=155}] list<filteringapples1.apple> heavyapples2 = filterapples(inventory, (filteringapples1.apple a) -> a.getweight() > 150); system.out.println(heavyapples2); // [] list<filteringapples1.apple> weirdapples = filterapples(inventory, (filteringapples1.apple a) -> a.getweight() a.getweight() > 150 );
就可以直接调用库方法 filter :
filter(inventory, (apple a) -> a.getweight() > 150 );
以上就是java8中predicate的用法介绍(代码示例)的详细内容。
