Lambda表达式

1.函数式编程思想概述

在数学中,函数就是有输入量、输出量的一套计算方案,也就是“拿什么东西做什么事情”。相对而言,面向对象过分强调“必须通过对象的形式来做事情”,而函数式思想则尽量忽略面向对象的复杂语法--强调做什么,而不是以什么形式做

面向对象的思想:

  做一件事情,找一个能解决这个事情的对象,调用对象的方法,完成事情

函数式编程思想:

  只要获取到结果,谁去做的,怎么做的都不重要,重视的是结果,不重视过程

2.Lambda表达式的标准格式

由三部分组成:

  一些参数

  一个箭头

  一段代码

格式:

  (参数列表)-> {一些重写方法的代码}

解释说明格式:

  ():接口中抽象方法的参数列表,没有参数,就空着;有参数,就写出参数,多个参数,使用逗号分隔

   -> :传递的意思,把参数传递给方法体

   {} :重写接口的抽象方法的方法体

案例1:Lambda表达式无参数无返回值

需求:

* 给定一个厨子Cook接口,内含唯一的抽象方法makeFood,且无参数,无返回值

* 使用Lambda标准格式调用invokeCook方法,打印输出“吃饭啦”字样

package cn.yjg.day10.Lambda;

/**
 * 需求:
 *  给定一个厨子Cook接口,内含唯一的抽象方法makeFood,且无参数,无返回值
 *  使用Lambda标准格式调用invokeCook方法,打印输出“吃饭啦”字样
 */

public class Demo01Cook {
    public static void main(String[] args) {
        // 调用invokeCook方法,参数是Cook接口,传递Cook接口的匿名内部类对象
        invokeCook(new Cook() {
            @Override
            public void makeFood() {
                System.out.println("吃饭啦");
            }
        });

        // 使用Lambda表达式简化匿名内部类的书写
        invokeCook(() -> {
            System.out.println("吃饭啦");
        });
    }

    // 定义一个方法,参数传递Cook接口,方法内部调用Cook接口中的方法makeFood
    public static void invokeCook(Cook cook) {
        cook.makeFood();
    }
}

  运行结果:

 案例2:Lambda表达式有参数有返回值的

需求:

使用数组存储多个Person对象

对数组中的Person对象使用Arrays的sort方法通过年龄进行升序排序

使用一般的方法

Person.java

package com.company.service.Lambda;

public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Person() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';
    }
}

  Demo01Arrays.java

package com.company.service.Lambda;

import java.util.Arrays;
import java.util.Comparator;

public class Demo01Arrays {
    public static void main(String[] args) {
        // 使用数组存储多个Person对象
        Person[] arr = {
            new Person("陈钰琪", 20),
            new Person("古力娜扎", 22),
            new Person("关之琳", 52),
        };

        // 对数组中的Person对象使用Arrays的sort方法通过年龄进行排序(前边-后边)
        Arrays.sort(arr, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getAge()-o2.getAge();
            }
        });

        // 遍历数组,使用增强for循环
        for (Person person : arr) {
            System.out.println(person);
        }
    }

}

  结果:

 使用Lambda,简化匿名内部类

package com.company.service.Lambda;

import java.util.Arrays;

public class Demo02Arrays {
    public static void main(String[] args) {
        // 使用数组存储多个Person对象
        Person[] arr = {
            new Person("陈钰琪", 20),
            new Person("古力娜扎", 22),
            new Person("关之琳", 52),
        };

        // 对数组中的Person对象使用Arrays的sort方法通过年龄进行排序(前边-后边)
        Arrays.sort(arr, (Person o1, Person o2) -> {
            return o1.getAge()-o2.getAge();
        });

        // 遍历数组,使用增强for循环
        for (Person person : arr) {
            System.out.println(person);
        }
    }

}

  案例3:

需求:

给定一个计算器Calculator接口,内含抽象方法calc可以将两个int数字相加得到和值

使用Lambda的标准格式调用invokeCalc方法,完成120和130的相加计算

 Calulator.java

package com.company.service.Lambda;

public interface Calculator {
    // 定义一个计算两个int整数和的方法并返回结果
    public abstract int calc(int a, int b);
}

  一般的方法

package com.company.service.Lambda;

public class Demo02Calculator {
    public static void main(String[] args) {
        // 调用invokeCalc方法,方法的参数是一个接口,可以使用匿名内部类
        invokeCalc(120, 130, new Calculator() {
            @Override
            public int calc(int a, int b) {
                return a+b;
            }
        });
    }

    /**
     * 定义一个方法,参数传递两个int类型的整数,
     * 参数传递Calculator接口,
     * 方法内部调用Calculator中的方法calc计算两个整数的和
     */
    public static void invokeCalc(int a, int b, Calculator c) {
        int sum = c.calc(a, b);
        System.out.println(sum);
    }

}

  使用Lambda简化匿名内部类

package com.company.service.Lambda;

public class Demo03Calculator {
    public static void main(String[] args) {
        // 调用invokeCalc方法,方法的参数是一个接口,可以使用匿名内部类
        invokeCalc(120, 130,(int a, int b) -> {
            return a+b;
        });
    }

    /**
     * 定义一个方法,参数传递两个int类型的整数,
     * 参数传递Calculator接口,
     * 方法内部调用Calculator中的方法calc计算两个整数的和
     */
    public static void invokeCalc(int a, int b, Calculator c) {
        int sum = c.calc(a, b);
        System.out.println(sum);
    }

}

 3.Lambda省略格式

可推导,那就可省略

Lambda强调的是“做什么”而不是“怎么做”,所以凡是可以根据上下文推导得知的信息,都可以省略,例如可以写成

invokeCalc(120, 130, (a, b) -> a+b);

  可以省略的内容:

(1)(参数列表):括号中参数列表的数据类型,可以省略不写

(2)(参数列表):括号中的参数如果只有一个,那么类型和()都可以省略

(3){一些代码}:如果{}中的代码只有一行,无论是否有返回值,都可以省略{},return,分号

注意:要省略这三个{},return,分号,必须要一起省略,

体现可推导可省略的例子

 4.Lambda使用前提

 1.使用Lambda必须具有接口,且要求接口中有且仅有一个抽象方法。

无论是JDK内置的Runnable,Comparator接口还是自定义的接口,只有当接口的抽象方法存在唯一时,才可以使用Lambda

 2.使用Lambda必须具有上下文推断

也就是方法的参数或局部变量的类型必须是Lambda对应的接口类型,才能使用Lambda作为该接口的实例

备注:

有且仅有一个抽象方法的接口,称为函数式接口

 

posted @ 2020-10-31 07:44  GumpYan  阅读(88)  评论(0编辑  收藏  举报