文本目录:
❄️一、背景:
➷ 1、Lambda表达式的语法:
➷ 2、函数式接口:
❄️二、Lambda表达式的基本使用:
➷ 1、语法精简:
❄️三、变量捕获:
❄️四、Lambda在集合中的使用:
☑ 1、Collection接口:
☑ 2、List接口:
☑ 3、Map接口:
❄️五、Lambda的优缺点:
☑ 1、优点:
☑ 2、缺点:
❄️总结:
❄️一、背景:
Lambda 表达式是Java SE 8中一个重要的新特性。lambda表达式允许通过表达式来代替功能接口。 lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体 。Lambda 表达式,基于数学中的 λ 演算得名,也可称为闭包。
➷ 1、Lambda表达式的语法:
基本语法:
(parameters) -> 方法体
其中:
parameters:类似方法中的形参列表,这里的参数是 函数式接口 里的参数。
这里的参数类型可以明确的声明也可不声明而由JVM隐含的推断。
另外当只有一个推断类型时可以省略掉圆括号。
-> :可以理解为 “被用于” 的意思。
方法体:可以是表达式也可以代码块,是函数式接口里方法的实现。
代码块可返回一个值或者什么都不反回,这里的代码块等同于方法的方法体。
如果是表达式,也可以返回一个值或者什么都不返回。
示例:
//1、不需要参数,返回值为10
() -> 10;
//2、接收一个参数(数字),返回其 3 倍的值
x -> 3 * x;
//3、接收两个参数,返回它们的和
(x,y) -> x + y;
//4、接收两个(int)类型的参数,返回它们的乘积
(int x,int y) -> x * y;
//5、接收一个 String,并在控制台打印,不返回任何值
(String s) -> System.out.println(s);
➷ 2、函数式接口:
函数式接口定义:一个接口有且只有一个抽象方法。
注意:
1、如果一个接口只有一个抽象方法,那么该接口就是 函数式接口
2、如果我们在某个接口上声明了 @FunctionalInterface 注解的话,那么编译器就会按照 函数式接口 的定义来要求该接口,这样当你放入两个抽象方法的时候就会报错。
函数式接口的定义方式:
@FunctionalInterface
interface IA {
void teat();
}
同样可以这样编写:
@FunctionalInterface
interface IA {
void teat();
default void teat2() {
System.out.println("default方法");
}
}
❄️二、Lambda表达式的基本使用:
我们来一个一个来看看如何使用的,我们先来看看一些接口:
//无返回值无参数
@FunctionalInterface
interface NoParameterNoReturn {
void test();
}
//无返回值一个参数
@FunctionalInterface
interface OneParameterNoReturn {
void test(int a);
}
//无返回值多个参数
@FunctionalInterface
interface MoreParameterNoReturn {
void test(int a,int b);
}
//有返回值无参数
@FunctionalInterface
interface NoParameterReturn {
int test();
}
//有返回值一个参数
@FunctionalInterface
interface OneParameterReturn {
int test(int a);
}
//有返回值多参数
@FunctionalInterface
interface MoreParameterReturn {
int test(int a,int b);
}
无返回值无参数:
//无返回值无参数
@FunctionalInterface
interface NoParameterNoReturn {
void test();
}
public class Test {
public static void main(String[] args) {
NoParameterNoReturn noParameterNoReturn = () -> {System.out.println("test的重写方法");};
noParameterNoReturn.test();
}
}
无返回值有一个参数:
//无返回值一个参数
@FunctionalInterface
interface OneParameterNoReturn {
void test(int a);
}
public class Test {
public static void main(String[] args) {
OneParameterNoReturn oneParameterNoReturn = (int a) -> {System.out.println(a);};
oneParameterNoReturn.test(20);
}
}
这个呢是可以 进行简化的,我们来看看简化后的:
//无返回值一个参数
@FunctionalInterface
interface OneParameterNoReturn {
void test(int a);
}
public class Test {
public static void main(String[] args) {
//OneParameterNoReturn oneParameterNoReturn = (int a) -> {System.out.println(a);};
OneParameterNoReturn oneParameterNoReturn = a -> System.out.println(a);
oneParameterNoReturn.test(20);
}
}
无返回值多个参数:
//无返回值多个参数
@FunctionalInterface
interface MoreParameterNoReturn {
void test(int a,int b);
}
public class Test {
public static void main(String[] args) {
//MoreParameterNoReturn moreParameterNoReturn = (int a,int b) -> {System.out.println(a+b);};
//简化后:
MoreParameterNoReturn moreParameterNoReturn = (a,b) -> System.out.println(a+b);
moreParameterNoReturn.test(10,20);
}
}
有返回值无参数:
//有返回值无参数
@FunctionalInterface
interface NoParameterReturn {
int test();
}
public class Test {
public static void main(String[] args) {
//NoParameterReturn noParameterReturn = () -> {return 20;};
//简化后:
NoParameterReturn noParameterReturn = () -> 20;
System.out.println(noParameterReturn.test());
}
}
有返回值有一个参数:
//有返回值一个参数
@FunctionalInterface
interface OneParameterReturn {
int test(int a);
}
public class Test {
public static void main(String[] args) {
//OneParameterReturn oneParameterReturn = (int a) -> {return a + 10;};
//简化后:
OneParameterReturn oneParameterReturn = (a) -> a + 10;
System.out.println(oneParameterReturn.test(20));
}
}
有返回值有多个参数:
//有返回值多参数
@FunctionalInterface
interface MoreParameterReturn {
int test(int a,int b);
}
public class Test {
public static void main(String[] args) {
//MoreParameterReturn moreParameterReturn = (int a,int b) -> {return a * b;};
//简化后:
MoreParameterReturn moreParameterReturn = (a,b) -> a * b;
System.out.println(moreParameterReturn.test(30, 2));
}
}
到这就简单的使用结束了,我们往后看:
➷ 1、语法精简:
1. 参数类型可以省略,如果需要省略,每个参数的类型都要省略。
2. 参数的小括号里面只有一个参数,那么小括号可以省略。
3. 如果方法体当中只有一句代码,那么大括号可以省略。
4. 如果方法体中只有一条语句,且是return语句,那么大括号可以省略,且去掉return关键字。
❄️三、变量捕获:
那么什么是 变量捕获 呢?我们在介绍 匿名内部类的时候呢,我们就有过 变量捕获 的这个情况,我们再重新来看一看:
这个 new 的 T 这个就是一个 匿名内部类,当我们定义一个变量 a 之后,如果改变的话,并且在 匿名内部类 中使用的话,那么就会报错,这个就是捕获变量。在其内部更改变量的值的话,同样会报错。这就是——变量捕获。
我们来看看 Lambda表达式 的变量捕获:
这就是 Lambda表达式 的变量捕获。
❄️四、Lambda在集合中的使用:
为了能让 Lambda 在Java的集合类中能更好的使用呢,在集合中呢,也添加了一些接口,以便于和 Lambda 使用。
对应的接口 | 新增的方法 |
Collection | removeIf()、stream()、spliterator()、parallelStream()、forEach() |
List | replaceAll()、sort() |
Map | getOrDefault()、forEach()、replaceAll()、remove()、replace()、putIfAbsent()、 computeIfAbsent()、computeIfPresent()、compute()、merge() |
可以去这里查询:
Java官网
有很多的接口,这里呢我们就简单的介绍几个就Ok了,我们一个个来看:
☑ 1、Collection接口:
我们这里演示一下其中的 forEach() 这个接口:
public class Test {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("abcd");
arrayList.add("world");
arrayList.add("hello");
arrayList.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
//简单遍历集合中的所有元素
System.out.println(s);
}
});
System.out.println("================");
//Lambda表达式:
arrayList.forEach(s -> System.out.println(s));
}
}
这个就是遍历集合中所有的元素。
☑ 2、List接口:
这个接口呢,我们来看看 sort() 接口:
这个是对其进行排序。
public class Test {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("abcd");
arrayList.add("world");
arrayList.add("hello");
arrayList.sort((o1,o2) -> o1.compareTo(o2));
arrayList.forEach(s -> System.out.println(s));
}
}
☑ 3、Map接口:
这里呢,我们介绍一下 forEach() 这个接口:
public class Test {
public static void main(String[] args) {
HashMap<String,Integer> map = new HashMap<>();
map.put("abc",3);
map.put("world",5);
map.put("hello",4);
map.forEach((key,val) -> System.out.println("key: " + key + " val: " + val));
}
}
❄️五、Lambda的优缺点:
☑ 1、优点:
1、 代码简洁,开发迅速
2、 方便函数式编程
3、 非常容易进行并行计算
4.、Java 引入 Lambda,改善了集合操作
☑ 2、缺点:
1、代码可读性变差
2、在非并行计算中,很多计算未必有传统的 for 性能要高
3、不容易进行调试
❄️总结:
OK,到这里呢,我们的 Lamdba表达式 呢到这里就结束了,这个呢不要感觉看起来有点难,但是呢在练习练习之后呢,这个呢就是非常简单操作了。到这里就结束了!!!拜拜~~~