java8 学习之路之lambda
前言
目前我们知道java的版本已经发布到12了,之前的项目用的是JDK1.7,听说JDK1.8的改动相对来说大一些,因此抽空学学JDK1.8的一些新特性。本人也是通过阅读Java8实战这本书做一些小的总结,方便以后巩固,同时也为想学习Java1.8的人提供一些思路望大家多多包涵,有不对的地方请提出了我们一起学习。想要Java8实战这本书电子版的小伙伴可以留言告我可以发给你呦!
演变过程
这里我们通过一个简单的故事来引出神奇的Lambda。这里首先有一个苹果的实例,其包含简单的属性:颜色和重量。
1 public class Apple { 2 private int weight = 0; 3 private String color = ""; 4 5 public Apple(int weight, String color){ 6 this.weight = weight; 7 this.color = color; 8 } 9 // get/set/toString 10 }
首先我们要获取红色的苹果(因为红色的好吃嘛),这时候我们会定义一个简单的方法来进行过滤获取到红色的苹果。
1 /** 2 * 筛选红苹果 3 * @param inventory 4 * @return 5 */ 6 public static List<Apple> filterRedApples(List<Apple> inventory){ 7 List<Apple> result = new ArrayList<>(); 8 9 for (Apple apple: inventory){ 10 if ("red".equals(apple.getColor())) { 11 result.add(apple); 12 } 13 } 14 15 return result; 16 }
后来由于苹果收购商有来了,我不管什么苹果,只要重量大于150g的统统给我装上车!好办啦!我们再加个方法来进行过滤就可以了。
/** * 筛选重量大于150的苹果 * @param inventory * @return */ 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; }
过了几天水果商又来了,我们现在想要绿色的苹果。这时候你可能想到是加一个方法 filterGreenApples 专门过滤绿色苹果,然而,如果要筛选多种颜色呢?黄色?暗红色?难道我们要每个新加一个方法吗?当然不是!我们最开始想到的是吧颜色作为参数传进去,试着将其抽象化。
1 public static List<Apple> filterApplesByColor(List<Apple> inventory, 2 String color) { 3 List<Apple> result = new ArrayList<Apple>(); 4 5 for (Apple apple: inventory){ 6 if ( apple.getColor().equals(color) ) { 7 result.add(apple); 8 } 9 } 10 11 return result; 12 }
同时我们可能想到将获取重量的方法也进行优化
1 public static List<Apple> filterApplesByWeight(List<Apple> inventory, 2 int weight) { 3 List<Apple> result = new ArrayList<Apple>(); 4 5 for (Apple apple : inventory){ 6 if ( apple.getWeight() > weight ){ 7 result.add(apple); 8 } 9 } 10 11 return result; 12 }
这时候就很不错了,可(cao)爱(dan)的水果商又来了让我们提供一种方式来区分不同的属性进行过滤。OK! 我们进行优化!
1 public static List<Apple> filterApples(List<Apple> inventory, String color, 2 int weight, boolean flag) { 3 List<Apple> result = new ArrayList<Apple>(); 4 5 for (Apple apple: inventory){ 6 if ( (flag && apple.getColor().equals(color)) || 7 (!flag && apple.getWeight() > weight) ){ 8 result.add(apple); 9 } 10 } 11 12 return result; 13 }
你会发现这个方法中的flag很难让人读懂。而且如果水果商想要再根据不同的属性进行过滤呢?比如产地、形状,那么这个方案就不能满足我们的需求了。
那么我们如何应对这种多变的需求呢?让我们来定义一个接口对苹果过滤器进行建模。
1 public interface AppleFilter { 2 boolean test(Apple apple); 3 }
我们定义一个接口对苹果进行过滤,你可以定义多个实现类来选择不同的标准。
1 public class AppleGreenColorFiler implements AppleFilter { 2 @Override 3 public boolean test(Apple apple) { 4 return "green".equals(apple.getColor()); 5 } 6 } 7 8 public class AppleHeavyWeightFilter implements AppleFilter { 9 @Override 10 public boolean test(Apple apple){ 11 return apple.getWeight() > 150; 12 } 13 }
这种实现方式类似与策略模式,我们可以将这种行为的实现作为一个参数传递进去。
1 public static List<Apple> filterApples(List<Apple> inventory, AppleFilter appleFilter) { 2 List<Apple> result = new ArrayList<Apple>(); 3 4 for (Apple apple : inventory) { 5 if(appleFilter.test(apple)) { 6 result.add(apple); 7 } 8 } 9 10 return result; 11 }
这时候我们会发现我们的代码灵活很多了,可以应对水果商的各种需求了。而过滤的主要业务我们是在其实现类中进行定义的。我们甚至可以同时获取重量大于150并且是红色的苹果。
1 public class AppleRedAndHeavyFilter implements AppleFilter { 2 @Override 3 public boolean test(Apple apple) { 4 return "red".equals(apple.getColor()) && apple.getWeight() > 150; 5 } 6 }
这时候我们发现我们可以使用匿名内部类做代码的优化。并不需要每次都创建其实现类来完成。
1 List<Apple> redApples = filterApples(inventory, new AppleFilter() { 2 @Override 3 public boolean test(Apple apple) { 4 return "red".equals(apple.getColor()); 5 } 6 });
那么在Java8中我们怎么做呢?看好啦!
1 List<Apple> redApples = filterApples(inventory, (Apple apple) -> "red".equals(apple.getColor()));
这样的代码即简洁又容易读懂。
其他例子
其实这样的写法可以针对很多地方,例如我们在使用Comparator对集合中的数据进行排序的时候,再比如使用Runnable创建线程的时候。这里就不再举例了,希望大家自己在下面试试这几种方式。