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创建线程的时候。这里就不再举例了,希望大家自己在下面试试这几种方式。

posted @ 2019-04-12 09:18  brother_four  阅读(993)  评论(0编辑  收藏  举报