本篇内容摘自《Java8 实战》
在阅读本篇文章之前,我希望你能了解什么是行为参数化——它允许你定义一个代码块来表示一个行为,然后传递它,利用这个概念,你就可以编写更为灵活且可重复使用的代码。
在行为参数化那篇博客中,我们最后写出了这样的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class Demo4 { public static void main (String[] args) { List<Apple> apples = filterApplesByPredicate(AppleUtil.getApples(), new AppleGreenColorPredicate()); for (Apple apple : apples) { System.out.println(apple); } } public static List<Apple> filterApplesByPredicate (List<Apple> inventory, ApplePredicate predicate) { List<Apple> result = new ArrayList<>(); for (Apple apple : inventory) { if (predicate.test(apple)) { result.add(apple); } } return result; } }
这里有一个问题,我们要筛选绿色苹果的时候编写了一个类AppleGreenColorPredicate
去实现ApplePredicate接口,但是有时候这个方法可能只会使用一次,如果这时候还要按照上面的方法去做的话,就显得有些不太合适。那么我们要如何去做呢?这时候我们想到了一个匿名内部类,代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class Demo5 { public static void main (String[] args) { List<Apple> apples = filterApplesByColor(AppleUtil.getApples(), new ApplePredicate() { @Override public boolean test (Apple apple) { return "green" .equals(apple.getColor()); } }); for (Apple apple : apples) { System.out.println(apple); } } public static List<Apple> filterApplesByColor (List<Apple> inventory, ApplePredicate predicate) { List<Apple> result = new ArrayList<>(); for (Apple apple : inventory) { if (predicate.test(apple)) { result.add(apple); } } return result; } }
这样我们就可以不用创建一个实现类去实现ApplePredicate
接口,但是匿名内部类不太友好,它占用了很多空间,让我们的代码显得很笨重与啰嗦,让代码显得不那么易读。那有没有办法去解决这个问题呢,答案是有的,在java8中,我们可以使用lambda表达式 去改造之前的代码,如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class Demo6 { public static void main (String[] args) { List<Apple> apples = filterApplesByColor(AppleUtil.getApples(), apple -> "green" .equals(apple.getColor())); for (Apple apple : apples) { System.out.println(apple); } } public static List<Apple> filterApplesByColor (List<Apple> inventory, ApplePredicate predicate) { List<Apple> result = new ArrayList<>(); for (Apple apple : inventory) { if (predicate.test(apple)) { result.add(apple); } } return result; } }
我想你应该发现了,之前匿名内部类的地方被这样一句代码代替了——apple -> "green".equals(apple.getColor())
,在->
的左边是参数列表,apple是简写,我们可以写成这样——(Apple apple)-> "green".equals(apple.getColor())
,在->
的右边是函数主体,这样写让我们的代码变得简洁很多。之所以我们能使用lambda表达式是依赖于类型推断,这是由编译器通过上下文环境推断而出。
比如我们要对苹果的重量从大到小进行排序
1 2 3 4 5 public static void main (String[] args) { List<Apple> apples = AppleUtil.getApples(); apples.sort(Comparator.comparing(Apple::getWeight)); apples.forEach(System.out::println); }
当苹果的重量一样,我们按照苹果的颜色来排序也是可以做到的,如下
1 2 3 4 5 6 7 public class Demo7 { public static void main (String[] args) { List<Apple> apples = AppleUtil.getApples(); apples.sort(Comparator.comparing(Apple::getWeight).thenComparing(Apple::getColor)); apples.forEach(System.out::println); } }
未完待续。。。