Lambda表达式
例子:
(o1,o2) -> Interger.compare(o1,o2);
格式:
-> : lambda操作符
-> 的左边: lambda形参列表,对应着要重写的接口中的抽象方法的形参列表。
->的右边:lambda体。对应要接口的实现类要重写的方法的方法体
public void test1() {
Runnable r1 = new Runnable(){
public void run(){
System.out.println("aaa");
}
};
r1.run();
System.out.println("*******");
//无参形式
Runnable r2 = () -> {
System.out.println("aaa");
};
}
@Test
public void test2(){
Consumer<String> con = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
con.accept("haha");
System.out.println("*******");
//需要一个参数,但是没有返回值
//***要求接口中只有一个抽象方法
Consumer<String> con1 = (String s) -> {
System.out.println(s);
};
con1.accept("hah");
}
@Test
public void test3(){
Consumer<String> con = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
con.accept("haha");
System.out.println("*******");
//数据类型可以省略,因为可由编译器推断得出
Consumer<String> con1 = (s) -> {
System.out.println(s);
};
con1.accept("hah");
}
@Test
public void test5(){
Comparator<Integer> com1 = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
}
};
System.out.println(com1.compare(12,21));
System.out.println("**********");
//多参数且有返回值的情况
Comparator<Integer> com2 = (o1,o2) ->{
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
};
System.out.println(com2.compare(12,21));
}
@Test
public void test6(){
Comparator<Integer> com1 = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
};
System.out.println(com1.compare(12,21));
System.out.println("**********");
//单条语句的情况可以省略大括号,但要记得删掉return
Comparator<Integer> com2 = (o1,o2) -> o1.compareTo(o2);
;
System.out.println(com2.compare(12,21));
}
lambda表达式的本质:
> 一方面,lambda表达式作为接口的实现类的对象。
> 另一方面,lambda表达式是一个匿名函数
函数式接口
定义:如果接口中只声明有一个抽象方法,则此接口就称为函数式接口。
只有给函数式接口提供实现类的对象时,我们才可以使用lambda表达式。
api中函数式接口所在包
jdk8中声明的函数式接口都在java.util.function包下。
4个基本函数式接口
方法引用
方法引用可以看作是基于lambda表达式的进一步刻画。
当需要提供一个函数式接口的实例时我们可以用lambda表达式提供此实例,当满足一定条件的情况下,我们还可以使用方法引用或构造器引用替换lambda表达式。
本质
方法引用作为了函数式接口的实例。
格式
类(或对象):: 方法名
具体情况:
情况1: 对象:: 实例方法
要求:函数式接口中抽象方法a与其内部实现时调用的对象的方法b的形参列表和返回值类型都相同时,可以考虑使用方法b实现对方法a的替换,覆盖。 注意:此方法b是非静态方法,需要对象调用
@Test
public void test1(){
//抽象方法的形参列表为s返回值类型为void
Consumer<String> con1 = s -> System.out.println(s); //System.out的println方法形参也为s,返回值类型为void所以可以用方法引用
con1.accept("hah");
System.out.println("*********");
Consumer<String> con2 = System.out :: println;
con2.accept("hah");
};
情况2:类::静态方法
要求:函数式接口中抽象方法a与其内部实现时调用的类的某个静态方法b的形参列表和返回值类型都相同时,可以考虑使用方法b实现对方法a的替换,覆盖。 注意:此方法b是静态方法,需要类调用
public void test2(){
//
Comparator<Integer> com1 = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(o1,o2);
}
};
Comparator<Integer> com2 = Integer :: compare;
}
情况3:类::实例方法
要求:函数式接口中的抽象方法a与其内部实现时调用的对象的某个方法b的返回值类型相同,同时,抽象方法a中有n个参数,方法b有n-1个参数,且抽象方法a的第一个参数作为方法b的调用者,且a的后n-1个参数与方法b的n-1个参数的类型相同。
public void test3(){
Comparator<String> com1 =new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
};
//lambda
Comparator<String> com2 = (o1,o2) -> o1.compareTo(o2);
//方法引用
//第一个参数是方法的调用者时,且满足返回值类型相同,可以使用
Comparator<String> com3 = String :: compareTo;
}
构造器引用
格式:
类名::new
说明:调用了类名中对应的类的某一确定的构造器,通过函数时接口的抽象方法的形参列表来确定调用的具体是哪一个构造器。
public void test4(){
Supplier<Employee> a = new Supplier<Employee>() {
@Override
public Employee get() {
return new Employee();
}
};
System.out.println(a.get());
//lambda
Supplier<Employee> b = () -> new Employee();
System.out.println(b.get());
//方法引用
Supplier<Employee> c = Employee::new;
}
数组引用
格式:数组名[] :: new
public void test5(){
Function<Integer,Employee[]> a = new Function<Integer, Employee[]>() {
@Override
public Employee[] apply(Integer integer) {
return new Employee[integer];
}
};
System.out.println(a.apply(5));
//lambda
Function<Integer,Employee[]> b = integer -> new Employee[integer];
System.out.println(b.apply(6));
//数组引用
Function<Integer,Employee[]> c = Employee[] :: new;
}