Lambda简介
Lambda 表达式是 JDK8 的一个新特性,可以取代大部分的匿名内部类,写出更优雅的 Java代码,尤其在集合的遍历和其他集合操作中,可以极大地优化代码结构。
JDK 也提供了大量的内置函数式接口供我们使用,使得 Lambda 表达式的运用更加方便、高效。
对接口的要求
虽然使用 Lambda 表达式可以对某些接口进行简单的实现,但并不是所有的接口都可以使用 Lambda 表达式来实现。Lambda规定接口中只能有一个需要被实现的方法,不是规定接口中只能有一个方法
jdk 8 中有另一个新特性:default, 被 default 修饰的方法会有默认实现,不是必须被实现的方法,所以不影响 Lambda 表达式的使用。
@FunctionalInterface
修饰函数式接口的,要求接口中的抽象方法只有一个。 这个注解往往会和 lambda 表达式一起出现。
//1.无参数无返回值
@FunctionalInterface
public interface One {
void a();
}
//2.多参数无返回值
@FunctionalInterface
public interface Two {
void a(int a,int b);
}
//3.单参数无返回值
@FunctionalInterface
public interface Three {
void a(int a);
}
//4.无参数有返回值
@FunctionalInterface
public interface Four {
int a();
}
//5.单参数有返回值
@FunctionalInterface
public interface Five {
int a(int b);
}
//6.多参数有返回值
@FunctionalInterface
public interface Six {
int a(int a,int b);
}
格式:()->{}
简化参数类型:
package t;
public class Test {
public static void main(String[] args) {
//1、简化参数类型--无参数无返回值
One o=()->System.out.println("11111111111");
o.a();
//2、简化参数类型--多参数无返回值
Two t=(a,b)-> System.out.println(a*b);
t.a(3,4);
//3.简化参数类型--单参数无返回值
Three three=(a)-> System.out.println(a);
three.a(5);
//4.简化参数类型--无参数有返回值
Four four=()->3;
System.out.println(four.a());
//5.简化参数类型--单参数有返回值
Five five=(a)->a;
System.out.println(five.a(25));
//6.简化参数类型--多参数有返回值
Six six=(a,b)->a*b;
System.out.println(six.a(33, 4));
}
}
控制台输出结果:
由此可见,lambda表达式可以让代码看起来更简洁.
方法引用:
-
什么是方法引用呢?
在学习lambda表达式之后,我们通常使用lambda表达式来创建匿名方法。然后,有时候我们仅仅是调用了一个已存在的方法。在java8中,我们可以直接通过方法引用来简写lambda表达式中已经存在的方法。
这种特性就叫做方法引用。 其中方法引用的操作符是双冒号"::" -
经典情形:
(1)普通引用:
对象名::实例方法名
@Test
public void test1(){
//原来实现
PrintStream ps=System.out; //注意,System.out是一个对象
Consumer<String> con=(x)->ps.println(x);
con.accept("锄禾日当午");
//使用方法引用
Consumer<String>con2=ps::println;
con2.accept("汗滴禾下土");
}
@Test
public void test2(){
//原来实现
Emp emp = new Emp("谁知盘中餐");
Supplier<String>sup=()->emp.getName();
System.out.println(sup.get());
//使用方法引用
Emp emp2 = new Emp("粒粒皆辛苦");
Supplier<String>sup2=emp2::getName;
System.out.println(sup2.get());
}
System.out 底层是一个PrintStream流 对象:
println()方法的底层是一个实例方法:
所以调用这个方法可以使用方法引用来简写。
(2)类名::静态方法名
@Test
public void test3(){
//原来的实现
Comparator<Integer> com=(x,y)->Integer.compare(x,y);
System.out.println(com.compare(100, 99));
//使用方法的引用
Comparator<Integer> com2=Integer::compareTo;
System.out.println(com2.compare(100, 99));
}
(3)类名::实例方法名
@Test
public void test4(){
//原来的实现
BiPredicate<String,String> bp=(x,y)->x.equals(y);
//使用方法的引用
BiPredicate<String,String> bp2=String::equals;
}
注意:
- Lambda体中调用方法的参数列表与返回值类型,要和函数式接口中抽象方法的参数列表和返回值类型保持一致!
- 若Lambda参数列表中的第一个参数是 实例方法的调用者,而第二个参数是实例方法的参数时,可以使用 ClassName::method
(4)构造方法引用:
@Test//无参构造
public void test5(){
//原来的实现
Supplier<Emp> sup=()->new Emp();
Emp emp = sup.get();
//构造器引用
Supplier<Emp> sup2=Emp::new;
Emp emp1 = sup2.get();
}
@Test//有参构造
public void test6(){
//原来的实现
Function<String,Emp> fun=(x)->new Emp(x);
Emp emp = fun.apply("厚溥");
//构造器引用
Function<String,Emp> fun2=Emp::new;
Emp emp2 = fun2.apply("厚溥");
}
注意:
需要调用的构造器参数列表要与函数式接口中抽象方法的参数列表保持一致!
- 数组引用:
@Test
public void test7(){
//原来的实现
Function<Integer,String[]> fun=(x)->new String[x];
String[] arrs = fun.apply(10);
//构造器引用
Function<Integer,String[]> fun2=String[]::new;
String[] arrs2 = fun2.apply(20);
}
总结
简单地说,就是一个Lambda表达式。在Java
8中,我们会使用Lambda表达式创建匿名方法,但是有时候,我们的Lambda表达式可能仅仅调用一个已存在的方法,而不做任何其它事,对于这种情况,通过一个方法名字来引用这个已存在的方法会更加清晰,Java
8的方法引用允许我们这样做。方法引用是一个更加紧凑,易读的Lambda表达式,注意方法引用是一个Lambda表达式,其中方法引用的操作符是双冒号"::"。