zoukankan      html  css  js  c++  java
  • JDK8--02:为什么要使用lambda

    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);//循环打印
        }
  • 相关阅读:
    noip2011 总结
    noip2010 总结
    noip2009 总结
    noip2008 总结
    noip2006总结
    noip2007 总结
    noip2006 总结
    【模板】线段树模板
    【数学】8.30题解-count数页码
    【数论】8.30题解-prime素数密度 洛谷p1835
  • 原文地址:https://www.cnblogs.com/liconglong/p/12185457.html
Copyright © 2011-2022 走看看