JAVA 8 新特性之 为什么要使用 Lambda 表达式?


前序 Lambda 表达式 介绍:

    1:在 java 8 中引入了一个新的操作符"->",该操作符称为箭头操作符Lambda操作符2:箭头操作符将Lambda表达式才分为两部分。
       左侧:Lambda 表达式的参数列表。
       右侧:Lambda 体,即对接口的实现

  3:学习 Lambda 表达式先 应该了解一个知识点 ”函数式接口“,使用 Lambda 表达式必须要有“
函数式接口”支持。
    了解地址:https://www.runoob.com/java/java8-functional-interfaces.html

 

@FunctionalInterface 注解:

该注解能够强制要求接口为 ”函数式接口“

代码演示:不用 @FunctionalInterface  注解:

package com.test.factory;

public interface FunctionalInterfaceTest {

    /**
     * 获取 用户姓名
     * @return
     */
    String getName();

    /**
     * 获取用户年龄
     */
    void getage();
}

代码演示:使用 @FunctionalInterface  注解: 存在了多个 抽象方法,所以指定 该注解 会报错,意思就是该接口必须指定成 “函数式接口”。

若接口中存在 一个以上的抽象方法,就不能称之为 ”函数式接口", @FunctionalInterface 可以强制要求该类必须为“函数式接口”。

 若要定义 “函数式接口” 只需要保存一个 抽象方法 即可。用不用 @FunctionalInterface 注解都不重要

如下图:只保留一个 抽象方法,就是一个合法的 “函数式接口”。

 

经典的函数式接口:Runnable

学习过多线程的朋友应该很清楚这个 接口。

 

“函数式接口" 定义总结:

“函数式接口” 的含义:
    核心:就是为了支持 Lambda 表达式 所定义的接口,
定义:“函数式接口” 必须保证 该接口 只有一个 抽象方法。
@FunctionalInterface注解:可以强制要求 该接口必须为 “函数式接口”。

 

 Lambda 表达式 优点:

Lambda 表达式 只有一个优点:,简化重复代码,只保留核心代码。使代码逻辑更加清晰。

 

Lambda 表达式 代码演示:

多说无益,看不到效果,即便说的天花烂醉又是如何?接下来统过一个 小小的案例,见识一下 Lambda 表达式 的 魅力之处。

需求:有一组员工信息存放到一个集合中,并且按照不同需求,来获取员工信息。

声明 
  案例展示中的案例 来源于 https://www.bilibili.com/video/av71563078?p=2 ,代码是我学习时按照视频课程内容讲解敲的(主要是想思考Lambda 的 演进过程,实际工作中用过Lambda,只是不知道是Lambda表达式,当时很傻的以为是idea 支持这么做)。
  记录博客,只是单纯的记录一下学习笔记,看别人的代码还不如自己动手敲一遍,找个差不多的案例。如有侵权,请联系我,我会主动删除
  
  对于内容思考有所不对的地方请指明出来,一起学习,一起进步。
  
  再次声明:以下代码只是我学习时,练手代码,对于质量我不敢保证,真正想学习 Lambda 的朋友,可以看视频教程或其他高质量的博客。

 案例展示:

  • 员工实体对象
    /**
     * @author Administrator
     * @version 1.0
     * @describe 员工信息 POJO
     * @date 2019/12/20 19:52
     */
    public class StaffModel {
        /**
         * 姓名
         */
        private String name;
        /**
         * 年龄
         */
        private int age;
        /**
         * 性别
         */
        private char gender;
        /**
         * 薪资
         */
        private double salary;
      
      get()...
      set()...
      toString()...
    }
  • 员工信息集:以下案例会都用这些数据。
    public class LambdaTest {
        private static List<StaffModel> staffModelList=new ArrayList<>();
    
        static {
            staffModelList.add(new StaffModel("张三",25,'男',5000));
            staffModelList.add(new StaffModel("村花",25,'女',5500));
            staffModelList.add(new StaffModel("李飞飞",21,'男',2000));
            staffModelList.add(new StaffModel("牛妞妞",30,'女',10000));
            staffModelList.add(new StaffModel("王晓非",24,'男',6000));
        }
    }

传统方式:

  • 案例一:普通的获取 工作大于或等于5000的 员工信息
    /**
         * 需求一:获取员工中 工资大于或五千的 员工信息
         * @return
         */
        public static List<StaffModel> salaryFilter(List<StaffModel> list){
            List<StaffModel> staffModelList=new ArrayList<>();
    
            for (int i = 0; i < list.size(); i++) {
                if (list.get(i).getSalary() >= 5000) {
                    staffModelList.add(list.get(i));
                }
            }
            return staffModelList;
        }
    
        /**
         * 测试
         * @param args
         */
        public static void main(String[] args) {
            System.out.println(salaryFilter(staffModelArrayList));
        }
    
        // 结果
    [StaffModel{name='张三', age=25, gender=男, salary=5000.0}, 
    StaffModel{name='村花', age=25, gender=女, salary=5500.0},
    StaffModel{name='牛妞妞', age=30, gender=女, salary=10000.0},
    StaffModel{name='王晓非', age=24, gender=男, salary=6000.0}] 
  •  案例二:获取 男性的员工信息

    /**
         * 需求二:获取男性员工信息
         * @return
         */
        public static List<StaffModel> genderFilter(List<StaffModel> list){
            List<StaffModel> staffModelList=new ArrayList<>();
    
            for (int i = 0; i < list.size(); i++) {
                if (list.get(i).getGender() == '男') {
                    staffModelList.add(list.get(i));
                }
            }
    
            return staffModelList;
        }
    
        /**
         * 测试
         * @param args
         */
        public static void main(String[] args) {
            System.out.println(genderFilter(staffModelArrayList));
        }
    
    
        //测试
        [StaffModel{name='张三', age=25, gender=男, salary=5000.0}, 
      StaffModel{name='李飞飞', age=21, gender=男, salary=2000.0},
      StaffModel{name='王晓非', age=24, gender=男, salary=6000.0}]
  • 整体代码展示:
    /**
         * 需求一:获取员工中 工资大于或五千的 员工信息
         * @return
         */
        public static List<StaffModel> salaryFilter(List<StaffModel> list){
            List<StaffModel> staffModelList=new ArrayList<>();
    
            for (int i = 0; i < list.size(); i++) {
                if (list.get(i).getSalary() >= 5000) {
                    staffModelList.add(list.get(i));
                }
            }
            return staffModelList;
        }
    
    
        /**
         * 需求二:获取男性员工信息
         * @return
         */
        public static List<StaffModel> genderFilter(List<StaffModel> list){
            List<StaffModel> staffModelList=new ArrayList<>();
    
            for (int i = 0; i < list.size(); i++) {
                if (list.get(i).getGender() == '男') {
                    staffModelList.add(list.get(i));
                }
            }
    
            return staffModelList;
        }
  • 总结与思考
    在传统方式中(如上例),面对不同的需求,我们需要 编写不同的方法(genderFilter()genderFilter()),来实现,但是核心代码只有一句,
    if (不同需求的条件(核心代码) {     staffModelList.add(list.get(i));   }
    若我们还有一个需求,获取年龄在25或25以上的员工信息,在传统方式中,我们无非就是再创建一个方法  copy 上面案例代码,更改 if(list.get(i).getAge()>=25) 这一句代码而已。
    因为这一句代码,我们需要写很多重复性代码,如需求一 和 需求二,其实我们要改变的只有 if 条件判断而已。其他代码都不会做任何改动。

    对于这样的代码,我们需要进行优化。只留核心,剔除其他

优化方式一:设计模式

  •  定义一个接口,由子类实现,完成过滤
    /**
     * 过滤 策略 接口
     * @author Administrator
     * @param <T>
     */
    public interface FilterStrategy<T> {
    
        boolean filter(T t);
    }
  • 创建一个子类,实现其接口,过滤规则由子类来定义
    /**
     * 薪资过滤,
     * 案例:过滤工资大于或等于 5000 的 员工
     * @author Administrator
     */
    public class SalaryFilter implements FilterStrategy<StaffModel> {
    
        @Override
        public boolean filter(StaffModel staffModel) {
            return staffModel.getSalary()>=5000;
        }
    }
  •  具体实现 案例一:普通的获取 工作大于或等于5000的 员工信息 

    /**
         * 员工过滤
         * @param list 员工信息集
         * @param strategy 过滤策略
         * @return
         */
        public static List<StaffModel> staffFilter(List<StaffModel> list,FilterStrategy<StaffModel> strategy){
            List<StaffModel> staffModelList=new ArrayList<>();
    
            for (int i = 0; i < list.size(); i++) {
                if (strategy.filter(list.get(i))) {
                    staffModelList.add(list.get(i));
                }
            }
    
            return staffModelList;
        }
    
        /**
         * 测试
         * @param args
         */
        public static void main(String[] args) {
            //采用 薪资过滤策略
            List<StaffModel> staffModelList=staffFilter(staffModelArrayList,new SalaryFilter());
            System.out.println(staffModelList);
        }
    
    // 测试结果
    [StaffModel{name='张三', age=25, gender=男, salary=5000.0}, 
    StaffModel{name='村花', age=25, gender=女, salary=5500.0}, 
    StaffModel{name='牛妞妞', age=30, gender=女, salary=10000.0}, 
    StaffModel{name='王晓非', age=24, gender=男, salary=6000.0}]
  • 具体实现 案例二: 获取 男性的员工信息
    /**
     *  案例二:获取员工中所有男性员工信息
     * @author Administrator
     */
    public class GenderFilter implements FilterStrategy<StaffModel> {
        
        @Override
        public boolean filter(StaffModel staffModel) {
            return staffModel.getGender()=='男';
        }
    }
    
      /**
         * 测试
         * @param args
         */
        public static void main(String[] args) {
            //采用 薪资过滤策略
            List<StaffModel> staffModelList=staffFilter(staffModelArrayList,new GenderFilter());
            System.out.println(staffModelList);
        }
    
    // 运行结果
    [StaffModel{name='张三', age=25, gender=男, salary=5000.0}, 
    StaffModel{name='李飞飞', age=21, gender=男, salary=2000.0},
    StaffModel{name='王晓非', age=24, gender=男, salary=6000.0}] 
  • 总结与思考:
    这里采用的设计模式 为策略设计模式,与之前按照不同的需求来创建方法的传统方式相比,设计模式减少了冗余代码量,方法只有一个方法,只是需要按照不同的需求创建策略就行了。减少了冗余代码。只关注于核心。符合了OCP 原则。 
  • 案例二展示:
        1:新建了一个过滤规则:性别过滤规则
        2:方法依旧是那个方法,只是main 方法 中的过滤规则变了。
    /**
     *  案例二:获取员工中所有男性员工信息
     * @author Administrator
     */
    public class GenderFilter implements FilterStrategy<StaffModel> {
    
        @Override
        public boolean filter(StaffModel staffModel) {
            return staffModel.getGender()=='男';
        }
    }
     
    
     /**
         * 员工过滤
         * @param list 员工信息集
         * @param strategy 过滤策略
         * @return
         */
        public static List<StaffModel> staffFilter(List<StaffModel> list,FilterStrategy<StaffModel> strategy){
            List<StaffModel> staffModelList=new ArrayList<>();
    
            for (int i = 0; i < list.size(); i++) {
                if (strategy.filter(list.get(i))) {
                    staffModelList.add(list.get(i));
                }
            }
    
            return staffModelList;
        }
    
        /**
         * 测试
         * @param args
         */
        public static void main(String[] args) {
            //采用 性别过滤策略
            List<StaffModel> staffModelList=staffFilter(staffModelArrayList,new GenderFilter());
            System.out.println(staffModelList);
        }

优化方式二:匿名内部类

  • 上一步方式的缺点:
    上一步的优化方式是采用策略模式,那么他有什么缺点呢?设计模式肯定是没有缺点,这是再这里的案例中比较浪费,只要凡是增加一个需求,就必须创建一个类,编写相对应的过滤策略。之所以说浪费,是因为类代码少,又不得不创建一个新类(心累),显得很浪费而已。
    所以这里又有一种优化方式,匿名内部类。
  • 代码展示:
      /**
         * 员工过滤
         * @param list 员工信息集
         * @param strategy 过滤策略
         * @return
         */
        public static List<StaffModel> staffFilter(List<StaffModel> list,FilterStrategy<StaffModel> strategy){
            List<StaffModel> staffModelList=new ArrayList<>();
    
            for (int i = 0; i < list.size(); i++) {
                if (strategy.filter(list.get(i))) {
                    staffModelList.add(list.get(i));
                }
            }
    
            return staffModelList;
        }
     /**
         * 测试 采用匿名内部类方式 进行过滤,过滤 年龄在 22 以上的员工信息
         * @param args
         */
        public static void main(String[] args) {
            List<StaffModel> staffModelList = staffFilter(staffModelArrayList, new FilterStrategy<StaffModel>() {
                @Override
                public boolean filter(StaffModel staffModel) {
                    return staffModel.getAge()>22;
                }
            });
    
            System.out.println(staffModelList);
        }
    
    //运行结果
    [StaffModel{name='张三', age=25, gender=男, salary=5000.0}, 
    StaffModel{name='村花', age=25, gender=女, salary=5500.0},
    StaffModel{name='牛妞妞', age=30, gender=女, salary=10000.0},
    StaffModel{name='王晓非', age=24, gender=男, salary=6000.0}]
  • 总结与思考
    对于上一种优化方式,不必再创建一个新的过滤器类。相对较而言,代码更少,更清晰。

     

优化方式三:Lambda 表达式

  • 如果你的是 Idea 你会发现当你写 匿名内部类的时候,他已经提示你可以进行优化了

     

  • 优化后的效果:代码已经缩短成了 两句代码 标志为 橙色 的就是我们需要的核心代码。
     /**
         * 测试
         * @param args
         */
        public static void main(String[] args) {
            List<StaffModel> staffModelList = staffFilter(staffModelArrayList, staffModel -> staffModel.getAge()>22);
            System.out.println(staffModelList);
        }
    
    // 运行结果
    [StaffModel{name='张三', age=25, gender=男, salary=5000.0}, 
    StaffModel{name='村花', age=25, gender=女, salary=5500.0},
    StaffModel{name='牛妞妞', age=30, gender=女, salary=10000.0},
    StaffModel{name='王晓非', age=24, gender=男, salary=6000.0}] 
  • 再来一个需求,获取名称为 “张三” 的员工信息
        /**
         * 测试
         * @param args
         */
        public static void main(String[] args) {
            List<StaffModel> staffModelList = staffFilter(staffModelArrayList, staffModel -> staffModel.getName().equals("张三"));
            System.out.println(staffModelList);
        }
    
    //运行结果
    [StaffModel{name='张三', age=25, gender=男, salary=5000.0}] 
  • 总结与思考
    Lambda 表达式 优化了我们代码,使我们的代码看起来,更加简单和清晰。Lambda 表达式 的支持,需要 jdk1.8 以上(听说 jdk 已经 都11了)而我实际工作中用的还是 jdk8,对jdk 8的特性了解甚少。惭愧

     

 优化方式四:Steam ApI

  • 应该是 jdk8 新的特性,不是很了解,直接代码展示吧
    public class LambdaTest {
        private static List<StaffModel> staffModelArrayList=new ArrayList<>();
    
        static {
            staffModelArrayList.add(new StaffModel("张三",25,'男',5000));
            staffModelArrayList.add(new StaffModel("村花",25,'女',5500));
            staffModelArrayList.add(new StaffModel("李飞飞",21,'男',2000));
            staffModelArrayList.add(new StaffModel("牛妞妞",30,'女',10000));
            staffModelArrayList.add(new StaffModel("王晓非",24,'男',6000));
        }
    
        /**
         * 测试
         * @param args
         */
        public static void main(String[] args) {
            staffModelArrayList
                    .stream()
                    .filter((e) -> e.getAge()>22) //过滤 年龄 大于 22 的员工信息
                    .forEach(System.out::println); // 进行打印 类似 System.out.println
        }
    
    }
    
    // 运行结果
    
    StaffModel{name='张三', age=25, gender=男, salary=5000.0}
    StaffModel{name='村花', age=25, gender=女, salary=5500.0}
    StaffModel{name='牛妞妞', age=30, gender=女, salary=10000.0}
    StaffModel{name='王晓非', age=24, gender=男, salary=6000.0} 
  • 除此之外还可以进行 向 sql 那样 分页(limit)
    /**
         * 测试
         * @param args
         */
        public static void main(String[] args) {
            staffModelArrayList
                    .stream()
                    .filter((e) -> e.getAge()>22)
                    //获取前两条数据
                    .limit(2) 
                    .forEach(System.out::println);
    
        }
    
    //运行结果
    StaffModel{name='张三', age=25, gender=男, salary=5000.0}
    StaffModel{name='村花', age=25, gender=女, salary=5500.0} 
  • 总结与思考
    除此之外,还有hash 等,都有很好的优化处理。只能感叹,更新太快,工作太忙,太多东西学不完。

 

 

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM