要想了解什么是lambda表达式,就必须得知道什么是函数式接口,函数式接口是指只包含一个抽象方法的接口。如果我们自己写一个函数时接口,最好在接口前添加@Functionallnterface,和@Override具有类似的作用,可以检查我们所写的接口是否正确。例如:
@FunctionalInterface
interface One{// 可以有其他的字段和方法,但是只能有一个抽象方法
void test();
}
(parameters) -> expression 或 (parameters) -> { statements;}
parameter : 方法中的参数列表,这里的方法指的是函数式接口中的抽象方法,注意这里的参数可以不写类型(要么全都写参数类型,要么全都不写参数类型)。
expression(表达式)/statements(代码块) : 是函数式接口中抽象方法的具体实现。
注意:
可以说,lambda表达式是匿名内部类的一种简写形式,但是还是有一定的区别,lambda表达式所需要的函数式接口只能有一个抽象方法,匿名内部类所需要的接口可以有多个抽象方法。
//无返回值无参数
@FunctionalInterface
interface NoParameterNoReturn {
void test();
}
public class Demo {
public static void main(String[] args) {
NoParameterNoReturn noParameterNoReturn = new NoParameterNoReturn() {
@Override
public void test() {
System.out.println("无参数");
}
};
//这两个语句的内容一样,上面是用匿名表达式,下面是用lambda表达式
NoParameterNoReturn noParameterNoReturn1 = () -> System.out.println("无参数");
}
}
//无返回值一个参数
@FunctionalInterface
interface OneParameterNoReturn {
void test(int a);
}
public class Demo {
public static void main(String[] args) {
OneParameterNoReturn oneParameterNoReturn
= (a) -> System.out.println("a");
//或 = a -> System.out.println("a");
}
}
//无返回值多个参数
@FunctionalInterface
interface MoreParameterNoReturn {
void test(int a,int b);
}
public class Demo {
public static void main(String[] args) {
MoreParameterNoReturn moreParameterNoReturn
= (a,b) -> System.out.println(a+b);
//或 = (int a, int b) -> System.out.println(a+b);
}
}
//有返回值无参数
@FunctionalInterface
interface NoParameterReturn {
String test();
}
public class Demo {
public static void main(String[] args) {
NoParameterReturn noParameterReturn
= () -> "hello";
//注:无参时,()不能省略
}
}
//有返回值一个参数
@FunctionalInterface
interface OneParameterReturn {
int test(int a);
}
public class Demo {
public static void main(String[] args) {
OneParameterReturn oneParameterReturn
= (a) -> {return a;};
//或 = a -> a;
}
}
//有返回值多参数
@FunctionalInterface
interface MoreParameterReturn {
int test(int a,int b);
}
public class Demo {
public static void main(String[] args) {
MoreParameterReturn moreParameterReturn
= (a,b) -> a + b;
//或 = (a,b) -> {return a+b;};
}
}
匿名内部类和lambda表达式中的变量捕获只适用于局部变量!!!
当在匿名内部类中引用外部类的局部变量时,这个局部变量必须声明为final或者实际上为final(即只赋值一次)。这是因为匿名内部类的实例可能会在外部方法执行完毕之后才被创建和使用,如果内部类可以修改外部局部变量,就可能导致不可预期的结果。
interface Str{
void print();
}
public class Demo2 {
public static void main(String[] args) {
int a = 10;
Str str = new Str() {
@Override
public void print() {
//a = 20;这样写会报错
System.out.println(a);
}
};
str.print();
}
}
在Lambda表达式中,可以访问的外部变量必须是隐式final或者实际上为final(即只在赋值一次)。
interface A{
void eat();
}
public class Demo3 {
public static void main(String[] args) {
int b = 10;
A a = () -> {
b = 3;
System.out.println(b);
};
a.eat();
}
}
注意:
对应的接口 | 新增的方法 |
Collection | removeIf() spliterator() stream() paralleStream() forEach() |
List | replaceAll() sort() |
Map | getOrDeflaut() forEach() replaceAll() putIfAbsent() remove() raplace() ...... |
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class Demo1 {
public static void main(String[] args) {
List list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list.add(i);
}
list.forEach(new Consumer() {
@Override
public void accept(Integer integer) {
System.out.print(integer +" ");
}
});
System.out.println();
list.forEach((x)-> System.out.print(x + " "));
}
}
import java.util.ArrayList;
import java.util.List;
public class Demo1 {
public static void main(String[] args) {
List list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list.add(10-i);
}
list.forEach((x)-> System.out.print(x + " "));
System.out.println();
list.sort((o1, o2) -> o1 - o2);
list.forEach((x)-> System.out.print(x + " "));
}
}
lambda表达式使代码更加简洁,但同时使代码的可读性变差,且不易调试