Lambda表达式
1 函数式编程思想
在数学中,函数就是有输入量、输出量的一套计算方案。在编程技术中,函数式编程(Functional Programming)是把函数作为基本运算单元,函数可以作为变量,可以接收函数,还可以返回函数。我们经常把支持函数式编程的编码风格称为Lambda表达式。
体验Lambda表达式
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/*
Lambda表达式体验 :
*/
public class LambdaDemo {
public static void main(String[] args) {
//将集合要以降序排序
List<Integer> list = new ArrayList<>();
list.add(100);
list.add(300);
list.add(200);
//集合以降序排序(以前的做法:匿名对象)
Collections.sort(list, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
//集合以降序排序(新做法:Lambda表达式)
Collections.sort(list,
(Integer o1, Integer o2) -> {
return o2 - o1;
}
);
}
}
2 函数式接口
只有一个抽象方法需要重写的接口就称为函数式接口。函数式接口允许存在其他的静态方法,默认方法,私有方法等,只对抽象方法有限制。
为了标识接口是一个函数式接口,可以在接口之上加上一个注解: @FunctionalInterface以示区别。
在JDK中 java.util.function 包中的所有接口都是函数式接口。
Comparator及线程的Runnable也是函数式接口。
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
我们也可以自定函数式接口
@FunctionalInterface
public interface Swim {
public abstract void swimming();
}
小结:
- 接口中只有一个抽象方法是需要被实现的就是函数式接口
- 函数式接口通常会有一个标志性注解:@FunctionalInterface
3 Lambda表达式格式
Lambda表达式其实就是对函数式接口匿名内部类的简写,简写到只有一个方法的重写。因此,Lambda表达式所表示的其实就是对函数式接口中抽象方法的重写。
Lambda表达式的标准语法:( 形参列表 ) -> { 方法体 }
就是将匿名内部类一直简化到只有一个方法的存在,而且方法可以进一步简化到只有参数列表,和方法体,中间加上语法箭头。
Lambda表达式的格式
格式:( 形式参数 ) -> { 代码块 }
形式参数: 和要写的函数式接口中抽象方法的参数列表一样
->: 由英文中画线和大于符号组成,固定写法。
方法体: 重写抽象方法的方法体
4 Lambda 省略规则
- 参数类型可以省略,但是有多个参数的情况下,不能只省略一个
- 如果参数有且仅有一个,那么小括号可以省略
- 如果代码块的语句只有一条,可以省略大括号和分号,甚至是return
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/*
Lambda表达式体验 :
*/
public class LambdaDemo {
public static void main(String[] args) {
//将集合要以降序排序
List<Integer> list = new ArrayList<>();
list.add(100);
list.add(300);
list.add(200);
//省略前
Collections.sort(list,
(Integer o1, Integer o2) -> {
return o2 - o1;
}
);
//省略后
Collections.sort(list, ( o1, o2) -> o2 - o1);
}
}
5 Lambda表达式和匿名内部类区别
- 所需类型不同
匿名内部类:可以是接口,也可以是抽象类,还可以是具体
Lambda表达式:只能是函数式接口 - 使用限制不同
如果接口中有且仅有一个抽象方法需要重写,可以使用Lambda表达式,也可以使用匿名内部类
如果接口中多于一个抽象方法,只能使用匿名内部类,而不能使用Lambda表达式 - 实现原理不同
匿名内部类:编译之后,产生一个单独的.class字节码文件
Lambda表达式:编译之后,没有一个单独的.class字节码文件。对应的字节码会在运行的时候动态生成