继续lamdba。上篇Java8 Lamdba表达式 002讲了使用lamdba对集合元素进行排序,本篇讲述使用lamdba对集合元素过滤,演示样例代码沿用上篇:
001
public class SortingPlayer { public static void main(String[] args) { List<Player> playerList = new ArrayList<>(); playerList.add(new Player("Black", "White", 9)); playerList.add(new Player("John", "Hello", 2)); playerList.add(new Player("Machicel", "Jackson", 7)); playerList.add(new Player("Ani", "Hessius", 4)); playerList.add(new Player("Mark", "Towns", 3)); playerList.add(new Player("Huge", "Nana", 6)); } } class Player{ //类定义參考上篇 }
如001所看到的 创建一个集合 并在集合中加入几条元素。名字。分数。如今要对集合中的元素进行过滤,比方我要获取全部分数大于等于5的元素把它们放到还有一个集合中,打印出符合条件的元素个数。
002
/** * Specifying Filter Criteria on a Collection of Data */ List<Player> bigGoals = new ArrayList<>(); playerList.stream().filter( p -> p.getGoals() >= 5) .forEach(element -> bigGoals.add(element)); System.out.println("Number of Players Matching Criteria: " + bigGoals.size());
002中新建一个集合用来保存符合条件的元素,使用stream因为它包括易用的过滤功能。依据playerList生成stream然后在上面调用过滤功能,过滤的处理使用了lamdba表达式。
lamdba表达式传递一个Player对象作为參数,然后依据条件goals>=5进行过滤。假设符合则往新建的集合加入这个元素。
通过以上的学习。我们应该对lamdba表达式有着深刻的印象了,它声明一个功能接口,也就是仅仅有一个抽象方法的接口,并用lamdba表达式实现。
或者使用Function<argument,return>定义。并实现。
在传统的Java类中。也有着仅仅有一个抽象方法的接口。比方新建一个线程java.util包下的Runnable接口,它里面仅仅有一个run抽象方法。如今我们考虑使用lamdba表达式实现Runnable接口。并跟传统的实现进行比較。
003
public class RunnableCompare { public static void main(String[] args) { Runnable oldRunnable = new Runnable() { @Override public void run() { int x = 5 * 3; System.out.println("The variable using the old way equals: " + x); } }; Runnable lambdaRunnable = () -> { int x = 5 * 3; System.out.println("The variable using the lambda equals: " + x); }; oldRunnable.run(); lambdaRunnable.run(); } }
因为java.util.Runnable是一个功能接口,实现接口之类的样板式的代码能够使用lamdba替换。Runnable里的抽象方法是无參数所以 參数列表是一对空的括号().
Runnable assignment = () -> {expression or statements};
假设你写过JavaSE的界面或者写过Android的代码,你可能会知道点击一个button的时候时候处理的方法里面有定义一个匿名的内部类,并对当中的方法进行实现,来处理button点击触发的动作。接下来我们讲讲怎样用lamdba表达式来代替这个繁冗的内部类实现代码。
003
import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.control.Button; public class ReplacingAnonymousInnerClasses { public static void main(String[] args) { Button btn = new Button(); /** * typical */ btn.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent e) { System.out.println("Do something... typical"); } }); /** * lambda */ btn.setOnAction(e ->{ System.out.println("Do something... lambda"); }); } }
003演示样例中:我们定义了一个button,为buttonbtn设置点击事件。
setOnAction,里面对button点击操作处理。
新建一个匿名类,然后实现当中的handle方法,很复杂,而接下来的演示样例中看到我们能够使用lamdba轻松搞定。
Lamdba表达式还能作为參数传递到方法中使用。
比方我要计算一个集合List<Double>每一个元素的乘积,通过以上的学习我们我们能够非常easy的写出这个功能:
004
import java.util.ArrayList; import java.util.List; import java.util.function.Function; public class Test { private static Double multiplyNum = 1d; public static void main(String[] args) { Function<List<Double>, Double> multiply = doubleList -> { doubleList.stream().forEach(num -> multiplyNum *= num); return multiplyNum; }; List<Double> list = new ArrayList<>(); list.add(12.3); list.add(25.6); list.add(38.4); multiply.apply(list); System.out.println(multiplyNum.intValue()); } }
ps:上面使用Function定义了Lamdba表达式用以计算集合元素的乘积,这里有一点注意。假设 multiplyNum定义在Main中,而不是在类的局部变量。那这里就会报错,Lamdba中在一个封闭范围内的变量必须是final或者表现是final的。你不能更改它的值。
Ok,写好了计算的方法,我们定义一个函数用以接收一个Lamdba表达式,以及要计算的元素集,然后返回计算的结果,方法例如以下:
005
public Double calculate(Function<List<Double>, Double> f1,Double[] args){ Double returnValue; List<Double> varList = new ArrayList<>(); int idx = 0; while (idx < args.length){ varList.add(args[idx]); idx++; } returnValue = f1.apply(varList); return returnValue; }
接下来加上Lamdba的实现并測试吧!
public class PassingLambdaFunctions { public Double calculate(Function<List<Double>, Double> f1,Double[] args){ //见005,此处省略 } public static void main(String[] args) { double x = 16.0; double y = 30.0; double z = 4.0; Function<List<Double>, Double> volumeCalc = list -> { if (list.size() == 3) { return list.get(0) * list.get(1) * list.get(2); } else { return Double.valueOf("-1"); } }; Double[] argList = new Double[3]; argList[0] = x; argList[1] = y; argList[2] = z; Function<List<Double>, Double> areaCalc = list -> { if (list.size() == 2) { return list.get(0) * list.get(1); } else { return Double.valueOf("-1"); } }; Double[] argList2 = new Double[2]; argList2[0] = x; argList2[1] = y; PassingLambdaFunctions p1 = new PassingLambdaFunctions(); System.out.println("The volume is: " + p1.calculate(volumeCalc, argList)); System.out.println("The area is: " + p1.calculate(areaCalc, argList2)); } }
不论什么类型的功能都能够使用Lamdba实现然后传递给不同的对象使用。这样能够更加提高代码的复用性&可维护性。Lamdba就说到这。假设不认为这些还不能满足你的需求,能够到官网去查找更详情的代码。或者搜索你想要的内容。
ps:本文演示样例引自 Josh Juneau所著 Java 8 Recipes, 2nd Edition
mission completed!
O(∩_∩)O~