• Lambda 表达式


    引言

    Lambda 表达式是 Java SE 8 中一个重要的新特性。其允许你通过表达式来代替功能接口。 lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(可以是一个表达式或一个代码块)。 此外,Lambda 表达式也可以看作是一个匿名函数,基于数学中的 λ 演算得名,也称为闭包。

    一、语法格式

    基本语法

    (parameters) -> expression;
    或
    (parameters) ->{ statements; }
    • 1
    • 2
    • 3

    Lambda表达式由三部分组成:

    1. paramaters:类似方法中的形参列表,这里的参数即为函数式接口里的参数。这里的参数类型可以明确声明,也可不声明,可由 JVM 推断。此外,当只有一个paramaters时,可以省略掉其对应圆括号。

    2. ->:可理解为“被用于”的意思。

    3. 方法体:可以是表达式也可以是代码块,是函数式接口里方法的实现。代码块可返回一个值或什么都不返回,这里的代码块等同于方法的方法体。如果是表达式,也可以返回一个值或者什么都不返回。

    二、理解函数式接口

    定义

    如果一个接口有且仅有一个抽象方法,那么该接口称为函数式接口。

    注意:如果我们在某个接口中声明了 @FunctionalInterface 注解,那么编译器就会按照函数式接口的定义来要求该接口。显然,当我们定义了两个抽象方法,程序编译就会报错。下面为函数式接口的语法

    @FunctionalInterface
    interface NoParameterNoReturn {
    	void test(); //注意:只能有一个抽象方法
    }
    
    • 1
    • 2
    • 3
    • 4

    三、使用 Lambda 表达式

    程序清单1:

    interface NoParameterNoReturn{
        void test();
    }
    
    public class Test1 {
        public static void main(String[] args) {
            
            //1. 正常实现一个接口
            //一般来说,接口不能直接通过 new 来实例化对象
            //但是我们可以通过 new 一个对象,相当于一个匿名内部类实现了此接口,
            //并重写其方法
            NoParameterNoReturn noParameterNoReturn = new NoParameterNoReturn() {
                @Override
                public void test() {
                    System.out.println("重写方法");
                }
            };
            noParameterNoReturn.test();
            System.out.println("-----------------");
            
            //2. 使用 Lambda 表达式
            NoParameterNoReturn noParameterNoReturn2 = () -> System.out.println("重写方法");
            noParameterNoReturn2.test();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    输出结果:

    out
    程序清单2:

    /**
     * 通过使用 Lambda 表达式来测试一些接口
     */
    interface OneParameterNoReturn {
        void test(int a);
    }
    
    interface MoreParameterNoReturn {
        void test(int a,int b);
    }
    
    interface NoParameterReturn {
        int test();
    }
    
    interface OneParameterReturn {
        int test(int a);
    }
    
    interface MoreParameterReturn {
        int test(int a,int b);
    }
    
    public class Test2 {
        public static void main(String[] args) {
            //1. 一个参数无返回值
            //形式一
            OneParameterNoReturn oneParameterNoReturn = (a)-> {System.out.println(a);};
            //形式二
            OneParameterNoReturn oneParameterNoReturn2 = a-> System.out.println(a);
            oneParameterNoReturn2.test(10);
            System.out.println("----------------------");
    
            //2. 多个参数无返回值
            //形式一
            MoreParameterNoReturn moreParameterNoReturn = (int a, int b)->{
                System.out.println(a+b);
            };
            //形式二
            MoreParameterNoReturn moreParameterNoReturn2 = (a,b)-> System.out.println(a+b);
            moreParameterNoReturn2.test(10,20);
            System.out.println("----------------------");
    
            //3. 无参数有返回值
            //形式一
            NoParameterReturn noParameterReturn = ()->{return 111;};
            //形式二
            NoParameterReturn noParameterReturn2 = ()->111;
            System.out.println(noParameterReturn2.test());
            System.out.println("----------------------");
    
            //4. 一个参数有返回值
            OneParameterReturn oneParameterReturn = (a)->a+5;
            System.out.println(oneParameterReturn.test(100));
            System.out.println("----------------------");
    
            //5. 多个参数有返回值
            MoreParameterReturn moreParameterReturn = (a,b)->a*b;
            System.out.println(moreParameterReturn.test(5, 5));
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    输出结果:

    out

    四、变量捕获

    程序清单3:

    /**
     * 变量捕获
     */
    
    class Out{
        public void function(){
            System.out.println(123);
        }
    }
    
    interface NoParameterNoReturn2 {
        void test();
    }
    
    public class Test3 {
        public static void main(String[] args) {
            //1. 将 x 这个变量视为常量,或者这个 x 变量不能被修改
            //这样一来,下面的匿名内部类才能捕获到变量 x
            int x = 111;
            //x = 999; //error
            new Out(){
                @Override
                public void function() {
                    System.out.println("捕获变量: " + x);
                }
            }.function();
    
            //2. 同理,下面是 Lambda 的变量捕获
            int a = 333;
            //a = 999; //error
            NoParameterNoReturn2 noParameterNoReturn2 = ()->{
    
                System.out.println("捕获变量:"+ a);
            };
            noParameterNoReturn2.test();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    输出结果:
    out

    五、Lambda在集合当中的使用

    程序清单4:

    import java.util.ArrayList;
    import java.util.Comparator;
    import java.util.function.Consumer;
    
    /**
     * Lambda 表达式在集合当中的使用
     */
    
    public class Test4 {
        public static void main(String[] args) {
            ArrayList<String> list = new ArrayList<>();
            list.add("hello");
            list.add("world");
            list.add("nice");
    
            /**
             * 1. 打印出来 list 中的现有元素
             * 方法一:
             * 直接通过匿名内部类实现 Consumer 这个函数式接口
             */
            list.forEach(new Consumer<String>() {
                @Override
                public void accept(String str) {
                    System.out.println(str);
                }
            });
            System.out.println("---------------------");
    
            //方法二:
            //Lambda 表达式的应用
            list.forEach(str -> System.out.println(str));
            System.out.println("---------------------");
    
            /**
             * 2. 排序 list 中的现有元素
             * 方法一:
             * 直接通过 Comparator 这个函数式接口 new 一个对象
             */
            list.sort(new Comparator<String>() {
                @Override
                public int compare(String o1, String o2) {
                    return o1.compareTo(o2);
                }
            });
            System.out.println(list);
            System.out.println("---------------------");
    
            //方法二:
            //Lambda 表达式的应用
            list.sort((o1, o2) -> o1.compareTo(o2));
            System.out.println(list);
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    输出结果:

    out

    六、Lambda 表达式的优缺点

    Lambda表达式的优点很明显,在代码层次上来说,使代码变得非常的简洁。缺点也很明显,代码不易读。

    优点:

    ① 代码简洁,开发迅速
    ② 方便函数式编程
    ③ 非常容易进行并行计算
    ④ Java 引入 Lambda,改善了集合操作

    缺点:

    ① 代码可读性变差
    ② 在非并行计算中,很多计算未必有传统的 for 性能要高
    ③ 不容易进行调试

  • 相关阅读:
    关于c++中成员函数做友元的详细解释
    儿童防近视台灯哪个品牌好?盘点几款适合儿童使用的护眼灯
    go-micro教程 — 第二章 go-micro v3 使用Gin、Etcd
    Docker镜像下载慢/失败?Linux代理使用不便?想无Docker下载镜像?试试我这款开源项目吧
    pip安装Cartopy小白版
    【ASP.NET Core】MVC控制器的各种自定义:应用程序约定的接口与模型
    微信小程序发布流程
    VS Code 下载和安装教程
    Android 深入理解SurfaceView
    为Ubuntu网页设置稳定的数据隧道
  • 原文地址:https://blog.csdn.net/lfm1010123/article/details/125286079