码迷,mamicode.com
首页 > 其他好文 > 详细

JDK8--02:为什么要使用lambda

时间:2020-03-09 23:53:00      阅读:99      评论:0      收藏:0      [点我收藏+]

标签:tree   EDA   interface   span   return   arraylist   rri   操作   print   

lambda是一个匿名函数,我们可以把lambda理解为一个可以传递的代码(将代码像数据一样传递),可以写出更简洁更灵活的代码。
首先看一下原来的匿名内部类实现方式(以比较器为例)
    //原来的匿名内部类实现方式
    public void test1(){
        //定义一个匿名内部类comparator
        Comparator<Integer> comparator = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return Integer.compare(o1,o2);
            }
        };
        //将匿名内部类作为对象传入
        TreeSet<Integer> treeSet = new TreeSet<>(comparator);
    }

 以上代码实际上实际有用的代码只有两行(第7行),但是却需要写这么多代码,非常痛苦,lambda就很好的解决了该问题。

 lambda实现方式

    //lambda表达式实现
    public void test2(){
        //lambda表达式
        Comparator<Integer> comparator = (x,y)->Integer.compare(x,y);
        //将匿名内部类作为对象传入
        TreeSet<Integer> treeSet = new TreeSet<>(comparator);
    }

 通过以上可以看到,原来的多行代码,变为了一行实现,代码量大大减少,但是,如果只是这样的一个结论,显然不能说服人(匿名内部类我直接就可以一键生成,对开发来说影响并不是很大,反而要学习一个新的语法,这种投入产出比不太大)
 所以再举一个例子来说明lambda的优势:

 需求1:获取公司中年龄大于35岁的员工

  先创建实体类

package com.example.jdk8demo.lambda;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.ToString;

@Data
@RequiredArgsConstructor
@AllArgsConstructor
@ToString
public class Employer {
    private String name;
    private Integer age;
    private double salary;
}

  为了方便演示,就不再进行数据库操作,直接模拟一个员工集合

/**
     * 模拟员工集合
     */
    private List<Employer> list = Arrays.asList(
            new Employer("张三",18,2222.22),
            new Employer("李四",32,3333.33),
            new Employer("王五",52,4444.44),
            new Employer("赵六",44,5555.55),
            new Employer("田七",8,4235.32),
            new Employer("牛八",28,3256.52)
    );

  然后就是实现逻辑代码,我们一般会直接定义一个方法去实现,如下代码所示

/**
     * 查询年龄大于35岁的员工
     * @return
     */
    public List<Employer> getEmpolyerByAge(){
        List<Employer> employerList = new ArrayList<>();
        for (Employer employer : list){
            if(employer.getAge() > 35){
                employerList.add(employer);
            }
        }
        return employerList;
    }

  那么如果此时,又来了一个需求

 需求2:查询工资大于4000的员工

  我们还需要再写一个实现方法

/**
     * 查询工资大于4000的员工
     * @return
     */
    public List<Employer> getEmpolyerBySalary(){
        List<Employer> employerList = new ArrayList<>();
        for (Employer employer : list){
            if(employer.getSalary() > 4000){
                employerList.add(employer);
            }
        }
        return employerList;
    }

  可以发现,两个方法中,只有  employer.getAge() > 35 和 employer.getSalary() > 4000 是不同的,其余的代码都一样,如果后续还有新的类似需求增加,呢么冗余代码会越来越多,因此我们就需要对代码进行优化。

优化方案一:使用策略模式

  一般情况下,对于这种冗余代码,我们的优化会使用策略模式进行优化

  首先,先创建一个接口

package com.example.jdk8demo.lambda;

public interface EmpolyerService<T> {
    boolean filter(T t);
}

  然后针对不同的需求,做不同的实现类

  第一个实现类是针对查询年龄大于35的员工

package com.example.jdk8demo.lambda;

public class EmpolyerImplByage implements EmpolyerService<Employer> {
    @Override
    public boolean filter(Employer employer) {
        return employer.getAge() > 35;
    }
}

  第二个实现类是针对查询公司大于4000的员工

package com.example.jdk8demo.lambda;

public class EmpolyerImplBySalary implements EmpolyerService<Employer> {
    @Override
    public boolean filter(Employer employer) {
        return employer.getSalary() > 4000;
    }
}

  然后就是使用策略模式进行查询,方法的入参是接口的实现类,然后根据实现类中对接口方法的不同实现进行不同的处理。

/**
     * 使用策略模式查询员工信息
     * @param empolyerService
     * @return
     */
    public List<Employer> getEmpolyerList(EmpolyerService<Employer> empolyerService){
        List<Employer> employerList = new ArrayList<>();
        for (Employer employer : list){
            if(empolyerService.filter(employer)){
                employerList.add(employer);
            }
        }
        return employerList;
    }

  最后所有需求都统一调用新增的策略模式方法,具体的入参就是接口具体的实现类

/**
     * 优化一:采用策略模式
     */
    public void test5(){
        List<Employer> employerList = getEmpolyerList(new EmpolyerImplByage());
        for (Employer employer : employerList){
            log.info(employer.toString());
        }
        log.info("=============================================");
        employerList = getEmpolyerList(new EmpolyerImplBySalary());
        for (Employer employer : employerList){
            log.info(employer.toString());
        }
    }

  这种优化也有不好的地方,就是一个需求就要创建一个实现类,随着需求的增加,实现类会越来越多,所以可以进一步进行优化

优化方案二:使用匿名内部类

  由于采用策略模式,一个需求就需要创建一个实现类,导致文件增多,因此可以将策略模式改为使用匿名内部类,使用匿名内部类,仍然需要上述的过滤接口,但是无需再使用接口的实现类

/**
     * 优化方式二:匿名内部类
     */
    public void test6(){
        List<Employer> employerList = getEmpolyerList(new EmpolyerService<Employer>() {
            @Override
            public boolean filter(Employer employer) {
                return employer.getAge() > 20;
            }
        });
        for (Employer employer : employerList){
            log.info(employer.toString());
        }
        log.info("=============================================");
        employerList = getEmpolyerList(new EmpolyerService<Employer>() {
            @Override
            public boolean filter(Employer employer) {
                return employer.getSalary() > 3000;
            }
        });
        for (Employer employer : employerList){
            log.info(employer.toString());
        }
    }

  由此已经对应了本文刚开始的时候,匿名内部类中有用的代码实际就一行,但是缺需要写大量其他无用的代码,因此可以使用lambda进行优化。

优化方案三:使用lambda

/**
     * 优化方式七:lambda表达式
     */
    public void test7(){
        LambdaTest lambdaTest = new LambdaTest();
        List<Employer> employerList = lambdaTest.getEmpolyerList((e) -> e.getAge()>30);
        employerList.forEach(System.out::println);
        log.info("=============================================");
        employerList = lambdaTest.getEmpolyerList((e)->e.getSalary()>3000);
        employerList.forEach(System.out::println);
    }

  可以发现,使用lambda表达式后,代码简单、简洁。到此处,为什么要使用lambda已经描述完毕,但是对于java8来说,还有更简洁的优化方式,就是Stream流。

优化方式四:Stream流

  此种实现,不需要像前三种优化方式一样新建接口,这里直接使用流式过滤即可。

/**
     * 使用StreamAPI查询员工信息
     */
    public void test8(){
        list.stream()//流式处理
                .filter((e)->e.getSalary()>2000)//过滤出工资大于2000的员工
                .filter((e)->e.getAge()>30)//过滤出年龄大于30的员工
                .limit(2)//只查询前两条
                .forEach(System.out::println);//循环打印
    }

 

JDK8--02:为什么要使用lambda

标签:tree   EDA   interface   span   return   arraylist   rri   操作   print   

原文地址:https://www.cnblogs.com/liconglong/p/12185457.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!