java8之一文彻底弄懂lambda表达式

Java 8的一个大亮点是引入Lambda表达式,使用它设计的代码会更加简洁。而且可以更加适应不断变化的需求;

下面我们循序渐进从案例入手

一:传统的应对列表筛选的解决方案

下面给出一个例子:

public static List<Apple> filterApple(List<Apple> appleList){
        List<Apple> apples = new ArrayList<>();
        for (Apple apple : appleList) {
            if (Objects.equals(apple.getColor(), "green")){
                apples.add(apple);
            }
        }
        return apples;
    }

此代码的意思是从一堆苹果中筛选出绿色的苹果。

假如哪一天,这位农民伯伯不想筛选绿色的苹果,想筛选红色的苹果,那么我们应该怎么做呢?

最简单的方法就是将上述的代码复制过来,然后改个条件,

但是后续的需求变动是不确定,那么我们应该怎么面对这种变化的需求?

此时进阶的做法就是将条件作为参数传入filterApple方法中,例子如下

public static List<Apple> filterAppleByCondition(List<Apple> appleList,String color){
        List<Apple> apples = new ArrayList<>();
        for (Apple apple : appleList) {
            if (Objects.equals(apple.getColor(), color)){
                apples.add(apple);
            }
        }
        return apples;
    }

上述代码很完美的解决了筛选苹果颜色的各种需求,但是现在要对苹果的重量进行筛选呢?是不是懵逼了,那我们改写一下程序

public static List<Apple> filterApple(List<Apple> appleList,double weight){
        List<Apple> apples = new ArrayList<>();
        for (Apple apple : appleList) {
            if(Double.compare(apple.getWeight(),weight)>0){
                apples.add(apple);
            }
        }
        return apples;
    }

这样也完美的解决了筛选苹果的需求,但是,接下来又有需求要一套方法解决筛选苹果的颜色和重量,改写程序如下

/**
     * flag 为true则筛选颜色,flag为false筛选重量
     * @param appleList
     * @param color
     * @param weight
     * @param flag
     * @return
     */
    public static List<Apple> filterApple(List<Apple> appleList,String color,double weight,boolean flag){
        List<Apple> apples = new ArrayList<>();
        for (Apple apple : appleList) {
            if((!flag&&Double.compare(apple.getWeight(),weight)>0)||(flag&&Objects.equals(apple.getColor(), color))){
                apples.add(apple);
            }
        }
        return apples;
    }

上述代码有以下几个缺点:

1,flag含义不确定

2,此方法无法应对更加富有变化的需求

 

二,行为参数化

对筛选苹果这一需求进行建模。

现在我们的需求是对苹果的属性进行筛选,返回值是一个boolean类型,那么我们建立一个接口

public interface ApplePredicate {
    public boolean test(Apple apple);
}

此接口的实现即可作为筛选苹果的入参,作为一个行为参数传递给筛选苹果的方法

public class AppleColorPredicate implements ApplePredicate {
    @Override
    public boolean test(Apple apple) {
        return "green".equals(apple.getColor());
    }
}



public class AppleWeightPredicate implements ApplePredicate {
    @Override
    public boolean test(Apple apple) {
        return Double.compare(apple.getWeight(),30)>0;
    }
}

经过改造后的筛选苹果方法如下:

 public static List<Apple> filterApple(List<Apple> appleList,ApplePredicate predicate){
        List<Apple> apples = new ArrayList<>();
        for (Apple apple : appleList) {
            if(predicate.test(apple)){
                apples.add(apple);
            }
        }
        return apples;
    }

这种做法就是借鉴了策略模式。建立一个统一的上层接口,利用不用的实现作为策略;

我们现在迈出了行为参数化的第一步,但是很遗憾的是,我们的行为必须通过对象的形式传递给方法

那么,我们有没有办法直接将代码传递给方法呢?有的,lambda表达式

List<Apple> red = FilterAppleList.filterApple(appleList, apple -> {
            return Objects.equals(apple.getColor(), "red");
        });

 

posted @ 2020-09-13 23:41  itqczzz  阅读(261)  评论(0编辑  收藏  举报