Lambda表达式
Posted 行则将至
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Lambda表达式相关的知识,希望对你有一定的参考价值。
看mybatis-plus的时候,使用mybatisplus的自动填充,拿官方代码拷到自己的环境上时Idea提示warning
直接altenter,会修改成两个冒号的形式,两种都是lambda表达式的写法,没见过,开贴记录
Lambda表达式
一、简介
Lambda表达式时JDK8的一个新特性(现在都JDK17了(´・_・`)),可以取代大部分的匿名类,写出更
优雅
的代码。
二、使用范围
Lambda规定接口中
只能有一个需要被实现的方法
,除此之外,jdk8中另一个特性,default,被default修饰的方法会有默认实现,不是必须被实现的方法,因此不影响Lambda表达式的使用
三、函数式接口
如果一个接口中只有一个需要实现的方法,那么这个接口就是函数式接口,@FunctionalInterface注解诞生!该注解用来判断接口是否为函数式接口,为Lambda表达式服务
不是函数式接口
函数式接口
四、初体验~
1.接口
@FunctionalInterface
public interface LambdaInterface {
abstract void method(Integer num);
default void method2(){
System.out.println("this is method2");
}
}
2.实现接口(JDK5)
public class LambdaTest {
public static void main(String[] args) {
new LambdaInterface() {
// 匿名内部类
@Override
public void method(Integer num) {
System.out.println(num);
}
};
}
}
3.实现接口(JDK8)
public class LambdaTest {
public static void main(String[] args) {
//Lambda表达式 ()->{}
LambdaInterface lambdaInterface = (Integer num)->{
System.out.println(num);
};
}
}
五、Lambda简化写法
1.简化参数类型
传入两个参数,可以省略参数类型,
参数类型可以不同
,如a为Integer,b为String,可以直接省略
LambdaInterface lambdaInterface = (a,b)->{
System.out.println(a);
};
2.简化参数括号
只有一个参数,可以省略参数括号
LambdaInterface lambdaInterface = b->{
System.out.println(b);
};
3.简化方法体括号
如果方法体中只有一条语句,可以省略大括号,和ifelse一样
LambdaInterface lambdaInterface = b->System.out.println(b);
4.简化方法体
如果方法体中只有return语句,则可直接省略return关键字
LambdaInterface lambdaInterface = (a,b)->a;
六、Lambda应用
遍历集合
- 定义集合
List<String> list = Arrays.asList("Java","C++","Python","php");
- for遍历
for (String s : list) {
System.out.println(s);
}
- forEach遍历
标准的函数式接口!
里面还是fro循环,参数看不懂,他需要一个T我们直接传一个t,打印
list.forEach(t-> System.out.println(t));
打印出了集合中的信息!
- 简化
list.forEach(System.out::println);
七、JDK8 方法引用
1.静态方法引用(static method)
- 语法:classname::methodname 例如:Person::getAge
2.对象的实例方法引用
- 语法:instancename::methodname 例如:System.out::println
3.对象的超类方法引用
- 语法: super::methodname
4.类构造器引用
- 语法: classname::new 例如:ArrayList::new
5.数组构造器引用
- 语法: typename[]::new 例如: String[]:new
详解:https://blog.csdn.net/zhoufanyang_china/article/details/87798829
- 例子
@FunctionalInterface
interface Supplier<T> {
T get();
}
public class LambdaTest {
public static void main(String[] args){
User user = LambdaTest.create(User::new);
System.out.println(user);
}
public static User create(final Supplier<User> supplier) {
return supplier.get();
}
}
Lambda表达式中的表达式lambda和语句lambda区别
Lambda表达式可分为表达式lambda和语句lambda
表达式lambda:表达式位于 => 运算符右侧的lambda表达式称为表达式lambda
(input parameters) => expression //表达式lambda
例如
(x, y) => x == y
语句lambda:=> 运算符右侧是一个语句块,语句包含在大括号中
(input parameters) => {statement;} //语句lambda
例如:
(x, y) => {return x == y;}
这两者除了写法不一样,还有什么区别吗,用以下代码作为测试
using System; using System.Collections.Generic; namespace LinqTest { class Program { static void Main(string[] args) { List<int> list = new List<int> { 1, 3, 2, 4 }; var resultUsingExpressionLambda = list.FindAll(p => p < 3); Console.WriteLine("使用表达式lambda:"); foreach (var item in resultUsingExpressionLambda) { Console.WriteLine(item); } var resultUsingStatementLambda = list.FindAll(p => { return p < 3; }); Console.WriteLine("使用语句lambda:"); foreach (var item in resultUsingStatementLambda) { Console.WriteLine(item); } } } }
代码比较简单,就是分别使用表达式lambda和语句lambda找出小于3的数,然后输出来,结果如下
输出结果一样。
查看反编译后的代码
看来编译器做了处理,两者的代码都是一样了,既然这样,那么在语句lambda中多加一行代码,Console.WriteLine(p); 这样就不会生成一样的代码了
Console.WriteLine(p.ToString());
using System; using System.Collections.Generic; namespace LinqTest { class Program { static void Main(string[] args) { List<int> list = new List<int> { 1, 3, 2, 4 }; var resultUsingExpressionLambda = list.FindAll(p => p < 3); Console.WriteLine("使用表达式lambda:"); foreach (var item in resultUsingExpressionLambda) { Console.WriteLine(item); } var resultUsingStatementLambda = list.FindAll(p => { Console.WriteLine(p);//这是新加的 return p < 3; }); Console.WriteLine("使用语句lambda:"); foreach (var item in resultUsingStatementLambda) { Console.WriteLine(item); } } } }
再查看反编译后的代码
再来看下IL代码
可以看到,无论是表达式lambda还是语句lambda,最后都生成一个方法,这里生成的方法分别是和,然后将方法赋给委托变量,就是这部分:
所以,给委托变量赋值时,表达式lambda和语句lambda写法不一样,但是最后编译器都生成一个方法。
还有个不同点,表达式lambda可以转换为类型Expression<T>的表达式树,而语句lambda不可以
Expression<Func<int, int, int>> expression = (a, b) => a + b;//正确 Expression<Func<int, int, int>> expression1 = (a, b) => { return a + b; };//错误,无法将具有语句体的 lambda 表达式转换为表达式树
//但是他们都可以赋给一个Func
Func<int, int, int> fun = (a, b) => a + b;//正确
Func<int, int, int> fun1 = (a, b) => { return a + b; };//正确
以上是关于Lambda表达式的主要内容,如果未能解决你的问题,请参考以下文章