目录
一.什么是lambda表达式
Lambda
表达式是
Java SE 8
中一个重要的新特性。
lambda
表达式允许你通过表达式来代替功能接口。
lambda
表达 式就和方法一样,
它提供了一个正常的参数列表和一个使用这些参数的主体
(body,
可以是一个表达式或一个代码块)
。
Lambda
表达式(
Lambda expression
)可以看作是一个匿名函数。
使用lambda表达式可以使代码的规模变小,看起来比较干净整洁,但是不容易理解,但是我们学习之后就会觉得lambda表达式会特别好用,但是使用也是有条件的。
二.lambda表达式的语法及使用实例
注意:只有函数式接口才可以使用lambda表达式,若为其他普通接口则不能够使用lambda表达式
1. 语法
(parameters) -> expression
或
(parameters) ->{ statements; }
(1)parameters相当于形参列表,当只有一个参数时括号也可以省略,没有参数时括号不能省略,其中里面的参数也可以省略类型,我们在使用的时候一般不给类型(使用lambda就是为了简单,能省则省)。
(2)->可以理解为“被用于”的意思
(3)->后面可以是表达式也可以是代码块(相当于方法体),对于返回值来说,可以返回一个值,也可以什么都不返回,根据自己需要使用函数式接口中的函数来判断是否需要返回。
//1.无参有返回值
() -> 0
//2.有类型,有返回值
(int a, int b) -> a + b
//3.有参无返回值
(String s) System.out.println(s)
//4.对于方法体中有多行时,大括号不能进行省略
(a,b) -> {
System.out.println("这里求的是2个数的乘积");
//如果有返回值,那么return不能进行省略
return a * b;
};
2.函数式接口
使用lambda表达式的前提是函数式接口,所以接下来我们介绍什么是函数式接口
函数式接口的定义:一个接口只有一个抽象方法,那么该接口就为函数式接口。
当我们写函数式接口时可以给该接口声明一个注解,这样编译器会自动给我们判断该接口是否为函数式接口,该声明为:@FunctionalInterface
注意:在jdk1.8及以上时,我们可以在函数式接口中使用一个default方法,里面可以有实现体,这样也可以为函数式接口。
代码举例如下:
//判断函数式接口
@FunctionalInterface
public interface FuncInterface {
//只有一个抽象方法
int func();
//默认方法(jdk1.8中的新特性)
default void print(){
System.out.println("函数式接口");
}
}
3.具体使用lambda表达式例子
(1)在函数式接口的条件下使用lambda表达式求2个数的和
函数式接口:
//判断函数式接口
@FunctionalInterface
public interface FuncInterface {
//只有一个抽象方法
int func(int a, int b);
//默认方法(jdk1.8中的新特性)
default void print(){
System.out.println("函数式接口");
}
}
在主函数中使用lambda表达式:
public class TestLambda {
public static void main(String[] args) {
FuncInterface fi = (a, b) -> a+b;
System.out.println(fi.func(10,20));
}
}
这里使用lambda表达式相当于对接口中的方法进行重写了,所以在下面调用之后打印的结果为30.
(2)对优先级队列中的Comparator接口使用lambda表达式,从而指定大顶堆还是小顶堆。
这里对于优先级队列中的大顶堆还是小顶堆使用了两种方法,一个是使用匿名内部类,另一个是lambda表达式。
代码如下:
import java.util.Comparator;
import java.util.PriorityQueue;
public class TestPriorityQueue {
public static void main(String[] args) {
//使用数组来验证是否为大顶堆还是小顶堆
int[] arr = {3,2,1,4};
//使用匿名内部类来指定优先级队列为小顶堆
PriorityQueue pq = new PriorityQueue(new Comparator<Integer>() {
@Override
public int compare(Integer num1, Integer num2) {
return num1 - num2;
}
});
for (int i = 0; i < arr.length; i++) {
pq.offer(arr[i]);
}
System.out.println(pq.peek());//1
//使用lambda从而指定为大顶堆
PriorityQueue<Integer> pq1 = new PriorityQueue<>((num1,num2) -> num2-num1);
for (int i = 0; i < arr.length; i++) {
pq1.offer(arr[i]);
}
System.out.println(pq1.peek());//4
}
}
三.lambda表达式和匿名内部类中的变量捕获
通过下面例子来说明关于变量捕获:
1.在lambda中的变量捕获
@FunctionalInterface
public interface FuncInterface {
int func(int a, int b);
}
public class VarCatch {
public static void main(String[] args) {
int a = 10;
FuncInterface fi = (num1,num2) -> {
a += 10;//这里会出现一个错误
return num1+num2;
};
}
}
2.在匿名内部类中的变量捕获
public static void main(String[] args) {
int a = 10;
FuncInterface fi = new FuncInterface() {
@Override
public int func(int a, int b) {
System.out.println(a);//可以再匿名内部类中使用外部变量
return 0;
}
};
}
四.关于lambda表达式的总结
1.优点:
(1)代码简洁,开发迅速
(2)方便函数式编程
(3)
非常容易进行并行计算
(4)Java
引入
Lambda
,改善了集合操作
2.缺点:
(1)
代码可读性变差
(2)在非并行计算中,很多计算未必有传统的
for
性能要高
(3)不容易进行调试