lambda表达式是java8的新特性。
为什么使用Lambda
Lambda是一个可传递的代码块,可以在以后传递一次或多次。Lambda可是对一个接口进行快速实现。
使用lambda表达式实现接口注意
接口必须是一个函数式接口(只有一个抽象方法需要实现的接口)。设计自己的lambda函数式接口可以在接口上加注解@FunctionInterface。
lambda基本语法
():写参数列表。
->:goes to参数方法连接符。
{}:写方法体。
简单的例子:
1、先定义接口
@FunctionalInterface
public interface LambdaBase {
int add(int a, int b);
}
2、测试代码
public class LambdaBaseTest {
public static void main(String[] args) {
//lambda表达式
LambdaBase lambdaBase = (a, b) -> {
return a + b;
};
//输出结果
System.out.println(lambdaBase.add(10, 20));
}
}
3、输出结果为30。
lambda语法简化
1、准备接口
@FunctionalInterface
public interface LambdaBase {
int add(int a, int b);
}
@FunctionalInterface
public interface LambdaOneParamNoReturn {
void test(String a);
}
2、测试代码
public class JianHua {
public static void main(String[] args) {
//1、参数只有一个可省略小括号
LambdaOneParamNoReturn lambdaOneParamNoReturn = a -> {
System.out.println("输出" + a);
};
lambdaOneParamNoReturn.test("apple");
//2、如果方法体只有一句,可以省略大括号
LambdaOneParamNoReturn lambdaOneParamNoReturn1 = a -> System.out.println("输出" + a);
lambdaOneParamNoReturn1.test("abc");
//3、如果方法体的唯一一句是返回语句,在省略大括号的同时要省略return关键字
LambdaBase lambdaBase = (a, b) -> a + b;
System.out.println(lambdaBase.add(1, 2));
}
}
方法引用
lambda方法引用是lambda指向的是一个具体的方法。
语法:方法隶属者::方法名。(方法隶属者是对象名或类名)。
注意:方法的参数列表、返回值必须与接口完全一样。
示例如下
1、接口
@FunctionalInterface
public interface LambdaBase {
int add(int a, int b);
}
2、测试
public class FangFaYinYong {
public static void main(String[] args) {
LambdaBase lambdaBase = FangFaYinYong::add;
System.out.println(lambdaBase.add(1, 2));
}
public static int add(int a, int b) {
return a + b;
}
}
输出结果3。
构造器引用
语法:构造的对象::new
示例:
1、对象
public class Student {
private String name;
private Integer age;
public Student() {
System.out.println("无参构造器执行了");
}
public Student(String name, Integer age) {
this.name = name;
this.age = age;
System.out.println("有参构造器执行了");
}
}
2、接口
/**
* 无参数接口
*/
@FunctionalInterface
public interface StudentNoParamConstruct {
Student getStudent();
}
/**
* 有参接口
*/
@FunctionalInterface
public interface StudentHaveParamConstruct {
Student getStudent(String name, int age);
}
3、测试
public class ConstructorTest {
public static void main(String[] args) {
//无参构造器引用
StudentNoParamConstruct studentNoParamConstruct = Student::new;
studentNoParamConstruct.getStudent();
//有参构造器引用
StudentHaveParamConstruct studentHaveParamConstruct = Student::new;
studentHaveParamConstruct.getStudent("jack", 20);
}
}
打印结果:
无参构造器执行了
有参构造器执行了
forEach遍历集合
语法:集合.forEach(lambda表达式)。
示例
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
Collections.addAll(list, 1, 2, 3, 4, 5, 6);
//打印集合元素
list.forEach(System.out::println);
//处理集合元素(输出大于5的元素)
list.forEach(ele -> {
if (ele > 5) {
System.out.println(ele);
}
});
}
removeIf
作用:删除集合中符合条件的元素。
示例
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
Collections.addAll(list, 1, 2, 3, 4, 5, 6);
//删除奇数
list.removeIf(elt -> elt % 2 != 0);
System.out.println(list);
}
打印结果:[2, 4, 6]
线程实现
示例
public static void main(String[] args) {
//用lambda实例化线程
java.lang.Thread thread = new java.lang.Thread(() -> {
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
});
thread.start();
}
java常用函数式接口
java常用函数式接口参考:https://www.runoob.com/java/java8-functional-interfaces.html
闭包
闭包会提升包围变量的生命周期(在方法结束后变量不会销毁)。
在使用lambda表达式时,在闭包中引用的变量一定是常量,举例说明:
public static void main(String[] args) {
int a = 5;
Consumer<Integer> consumer = elt ->
System.out.println(a++); //a++编译出错:Variable used in lambda expression should be final or effectively final
consumer.accept(1);
}
原因:只要在闭包中使用了某个局部变量值,就会将这个局部变量用final修饰,变量值不可更改。像上面这个例子变量a在编译时会以final int a = 5来编译。
6a