美文网首页
为什么要用Lambda表达式?(详细实例解释)

为什么要用Lambda表达式?(详细实例解释)

作者: Carter强 | 来源:发表于2020-08-21 14:07 被阅读0次

            在Java 8中,新增了Lambda表达式功能。那么,Lambda表达式能帮助我们干什么呢?

            下面我将用一个真实的例子一步步证明Lambda表达式将会给我们的Coding体验带来非凡的提升。

    使用场景如下:

            现在,农民伯伯给我们提了一个新的需求,他们希望我们可以开发一个组件,帮助农民伯伯从数量不等的苹果中过滤出绿色的苹果。

    为了完成这个需求,需要做如下设计

    Version 1:

    (1)编写一个苹果的实体类,主要包含三个属性:颜色,重量,品种。

    package org.example.lamdba;

    import java.util.Arrays;

    import java.util.List;

    public class Apple {

    private String color;

    private int weight;

    private String variety;

    /**

        * 空构造函数

        */

        public Apple(){

    }

    /**

        * 完全构造函数

        * @param color

        * @param weight

        * @param variety

        */

    public Apple(String color,int weight,String variety){

    this.color = color;this.weight = weight;this.variety = variety;}

    public String getColor() {return color;}

    public void setColor(String color) {this.color = color;}

    public int getWeight() {return weight;}

    public void setWeight(int weight) {this.weight = weight;}

    public String getVariety() {return variety}

    public void setVariety(String variety) {this.variety = variety;}

    public static List sampleList(){

    return Arrays.asList(

    new Apple("红色",150,"红富士"),new Apple("红色",149,"红富士"),new Apple("绿色",135,"青苹果"),new Apple("绿色",136,"青苹果"),

    new Apple("红色",155,"红富士"),new Apple("深红色",145,"红元帅"),new Apple("深红色",142,"红元帅")

    );}}

    (2): 编写一个Demo类,类名LambdaDemoV1,该Demo类中含有根据颜色过滤的三个方法,并且有可以直接运行的main方法(抱歉,本人不喜欢用Junit的test,哈哈)

    package org.example.lamdba;

    import java.util.ArrayList;

    import java.util.List;

    public class LambdaDemoV1 {

    public static void main(String[] args) {

    List apples = Apple.sampleList();

    List blueApples =filterGreenApples(apples);

    List redApples =filterRedApples(apples);

    List crimsonApples =filterCrimsonApples(apples);

    }

    //筛选绿苹果

        public static List filterGreenApples(List inventory){

    List result =new ArrayList<>();

    for(Apple apple:inventory){

    if("绿色".equals(apple.getColor())){

    result.add(apple);}}

    return result;

    }

    //筛选红苹果

        public static List filterRedApples(List inventory){

    List result =new ArrayList<>();

    for(Apple apple:inventory){

    if("红色".equals(apple.getColor())){

    result.add(apple);}}

    return result;

    }

    //筛选深红苹果

     public static List filterCrimsonApples(List inventory){

    List result =new ArrayList<>();

    for(Apple apple:inventory){

    if("深红色".equals(apple.getColor())){

    result.add(apple);}}

    return result;}}

            通过Version 1 版本的设计,我们已经基本完成了农民伯伯的要求,但是,作为开发者,我们需要对上述的通过苹果颜色筛选苹果的方法做一次整合,将颜色作为一个参数,防止添加一个颜色筛选功能就新添加一个方法。

    Version 2 :

    Coding如下:

    //根据苹果的颜色筛选苹果 重新设计filterGreenApples,filterRedApples,filterCrimsonApples方法 =>filterColorApples方法

    public static List filterColorApples(List inventory,String color){

    List result =new ArrayList<>();

    for(Apple apple:inventory){

    if(color.equals(apple.getColor())){

    result.add(apple);}}

    return result;}

             经过Version 2 版本的整合,农民伯伯已经可以方便的使用我们提供的工具筛选特定颜色的苹果。但是,现在农民伯伯又提出了一个新的需求,他希望我们可以向他提供一个筛选特定重量苹果的新功能,(农名伯伯将单个苹果的质量超过150g的成为重苹果,小于等于150g的称为轻苹果)

    Version 3 Coding: 如下

    public class LambdaDemoV3 {

    public static void main(String[] args) {

    List apples = Apple.sampleList();

    List blueApples =filterColorApples(apples,"绿色");

    List redApples =filterColorApples(apples,"红色");

    List crimsonApples =filterColorApples(apples,"深红色");

    List heavyApples =filterApplesByWeight(apples,150);

    }

    //根据苹果的颜色筛选苹果

    public static List filterColorApples(List inventory,String color){

    List result =new ArrayList<>();

    for(Apple apple:inventory){

    if(color.equals(apple.getColor())){

    result.add(apple);}}

    return result;}

    //根据苹果的重量筛选苹果

    public static List filterApplesByWeight(List inventory,int weight){

    List result =new ArrayList<>();

    for(Apple apple:inventory){

    if(apple.getWeight() > weight){

    result.add(apple);}}

    return result;}}

            在上面的版本中,新增功能方法filterApplesByWeight,农民伯伯可以通过将weight参数设置成150g方便的筛选出重量150g的苹果集。但是,这时,作为开发者,我们想到了这样一个问题,现在,农民伯伯只提出了通过颜色或者重量属性筛选苹果,要是接下来,农民伯伯希望通过产地,大小等苹果的其它属性进行筛选,怎么办,难道我们要一直增加新的方法吗?当然不是,通过观察学习现有的代码,我们发现其实真正因为功能变化而发生变化的代码只有 if(color.equals(apple.getColor())) => if(apple.getWeight() > weight),其它的都是样板代码(即处理流程)。我们是否可以换一个角度去思考解决这个问题呢?当然有,为此我们提出了一个新的解决方案,即 行为参数化。

    Version 4

    coding如下:

    public interface ApplePredicate {

    boolean test (Apple apple);}

    public class AppleGreenColorPredicateimplements ApplePredicate{

    @Override

        public boolean test(Apple apple) {

    return "绿色".equals(apple.getColor());}}

    public class AppleHeavyWeightPredicateimplements ApplePredicate{

    @Override

    public boolean test(Apple apple) {

    return apple.getWeight() >150;}}

    public class LambdaDemoV4 {

    public static void main(String[] args) {

    List apples = Apple.sampleList();

    List heavyApples =filterApples(apples,new AppleGreenColorPredicate());

    List greenApples =filterApples(apples,new AppleHeavyWeightPredicate());

    }

    public static List filterApples(List inventory,ApplePredicate p){

    List result =new ArrayList<>();

    for(Apple apple:inventory){

    if(p.test(apple)){

    result.add(apple);}}

    return result;}}

            在这个版本的Coding中,我们进行了建模,即创建了含有单个函数的接口ApplePredicate。该函数约定返回一个boolean值,而其具体实现需要使用者去创建。之后在改进版的filterApples方法中,将ApplePredicate p 传入参数。这样农民伯伯通过创建ApplePredicate的不同实现就可以使用filterApples提供的颜色,重量,品种等的不同筛选功能。

            从开发者的角度考虑,功能组件已经满足了农民伯伯的常用需求,api简单,易用。且开发者以极小的成本代价完成了丰富的功能需求。但是,通过观察代码,我们发现,农民伯伯在使用我们的filterApples时必须先创建实现一个ApplePredicate的子类,再应用filterApples方法。功能的确实现了,但是存在将代码的繁琐由开发者向使用者转嫁的嫌疑。

             通过分析,我们决定使用 匿名类的 方式对上述代码做一次优化。

    Version 5:

    public class LambdaDemoV5 {

    public static void main(String[] args) {

    List apples = Apple.sampleList();

    List heavyApples =filterApples(apples,new ApplePredicate(){

    @Override

    public boolean test(Apple apple) {

    return apple.getWeight() >150;}});

    List greenApples =filterApples(apples,new ApplePredicate(){

    @Override

    public boolean test(Apple apple) {

    return "绿色".equals(apple.getColor());}});}

    public static List filterApples(List inventory,ApplePredicate p){

    List result =new ArrayList<>();

    for(Apple apple:inventory){

    if(p.test(apple)){

    result.add(apple);}}

    return result;}}

    上述代码中使用了Java 匿名类的方式减少了代码量,但是依旧有些繁琐,接下来,我们可以使用最后一个大招,Lamdba表达式

    Version 6:

    public class LambdaDemoV6 {

    public static void main(String[] args) {

    List apples = Apple.sampleList();

    List heavyApples =filterApples(apples,(Apple apple) ->apple.getWeight() >150);

    List greenApples =filterApples(apples,(Apple apple) ->"绿色".equals(apple.getColor()));

    }

    public static List filterApples(List inventory,ApplePredicate p){

    List result =new ArrayList<>();

    for(Apple apple:inventory){

    if(p.test(apple)){

    result.add(apple);}}

    return result;}}

            查看上述代码,是不是足够骚浪贱。Java允许我们使用Lambda表达式替代传统的匿名类创建使用方式,当该参数接口是含有单个函数的函数式接口,我们就可以使用Lambda表达式去替代匿名类的使用方式。这就是Lambda的强大之处。极大缩短代码行数,同时大大提高代码的易读性。这时,我们去回看Version 1的代码,当时LambdaDemoV1实现的功能仅有筛选颜色,而且开发了不同的三个方法才完成,转到Version 6的代码,LambdaDemoV6的filterApples方法 可以满足 使用者对苹果的重量,颜色,品种等不同属性的过滤筛选,功能大大增强,同时,使用方面,仅需要农民伯伯编写 List heavyApples =filterApples(apples,(Apple apple) ->apple.getWeight() >150);简短的代码就可以使用了,嗨到爆!

    完成这篇博客我花费了将近一天的时间,如果有错误的地方,请及时联系我,谢谢!

    相关文章

      网友评论

          本文标题:为什么要用Lambda表达式?(详细实例解释)

          本文链接:https://www.haomeiwen.com/subject/enlejktx.html