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作为该接口的实例
备注:
有且仅有一个抽象方法的接口,称为函数式接口