一、lambda表达式
函数式接口:如果一个接口中,只声明一个抽象方法,则此接口就称为函数式接口
lambda表达式的本质是,作为函数式接口的实例
二、lambda格式
例如,对Comparator接口的compare()方法的实现:
public void test(){
Comparator<Integer> com1 = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
};
Comparator<Integer> com2 = (o1, o2) -> {
return o1.compareTo(o2);
};
Comparator<Integer> com3 = (o1, o2) -> o1.compareTo(o2);
}
形如,(o1, o2) -> o1.compareTo(o2)为lambda表达式:
-> : lambda操作符
左边:lambda形参列表(其实就是接口中的形参列表)。lambda形参列表参数可以省略,可以类型推断出;如果lambda形参列表只有一个参数,其一对()也可以省略
右边:lambda体(其实就是重写的抽象方法的方法体)。lambda应该用一对{}包裹;如果lambda体只有一条执行语句(可能是return语句),可以省略这一对{}和return关键字
三、举例代码
public void test1(){
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("r1");
}
};
r1.run();
Runnable r2 = () -> System.out.println("r2");
r2.run();
}
public void test2(){
Consumer<String> con1 = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
con1.accept("con1");
Consumer<String> con2 = s -> System.out.println("con2");
con2.accept("con2");
}
public void test3(){
Comparator<Integer> com = (o1, o2) -> o1.compareTo(o2);
}
四、自定义函数式接口
接口添加@FunctionalInterface注解,此注解会检查接口内抽象方法是否只有一个,如果不是一个,编译阶段会报错
@FunctionalInterface
public interface MyInterface {
void method();
}
五、四大核心函数式接口
六、方法引用
方法引用,本质上是lambda表达式,而lambda表达式作为函数式接口的实例,所以方法引用,也是函数式接口的实例
情况一:对象::实例方法名
情况二:类::静态方法名
情况三:类::实例方法名
方法引用使用的要求,要求接口中的抽象方法名的形参列表和返回值类型与方法引用的方法的形参列表和返回值类型相同(适用于情况一和情况二)
public class MethodRefTest {
public static void main(String[] args) {
}
/**
* 情况一:对象::实例方法
* Consumer中的void accept(T t)
* PrintStream中的void println(T t)
*/
public void test1(){
Consumer<String> con1 = new Consumer<String>() {
@Override
public void accept(String str) {
System.out.println(str);
}
};
Consumer<String> con2 = new Consumer<String>() {
@Override
public void accept(String str) {
PrintStream ps = System.out;
ps.println(str);
}
};
Consumer<String> con3= str -> System.out.println(str);
PrintStream ps = System.out;
Consumer<String> con4 = ps::println;
}
/**
* Supplier中的T get()
* Dog中的String getName()
*/
public void test2(){
Dog dog = new Dog("dog1");
Supplier<String> sup1 = () -> dog.getName();
Supplier<String> sup2 = dog::getName;
}
/**
* 情况二:类::静态方法
* Comparator中的int compare(T t1, T t2)
* Integer中的int compare(T t1, T t2)
*/
public void test3(){
Comparator<Integer> com1 = (t1, t2) -> t1.compareTo(t2);
Comparator<Integer> com2 = Integer::compare;
}
/**
* 情况三:类::实例方法
* Comparator中的int compare(T t1, T t2)
* String中的int t1.compareTo(t2)
*/
public void test4(){
Comparator<String> com1 = (s1, s2) -> s1.compareTo(s2);
Comparator<String> com2 = String::compareTo;
}
/**
* Function中的 R apply(T t)
* Dog中的String getName();
*/
public void test5(){
Function<Dog, String> func1 = e -> e.getName();
Function<Dog, String> func2 = Dog::getName;
}
}
class Dog{
private String name;
public Dog() {
}
public Dog(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
七、构造器引用和数组引用
构造器引用,和方法引用类似,函数式接口的抽象方法的形参列表和构造器的形参列表一致,抽象方法的返回值类型即为构造器所属的类的类型
数组引用,数组可以看做是一个特殊的类,则写法与构造器引用一致
public class ConstructorRefTest {
/**
* 构造器引用
* Supplier中的T get()
* Dog的空参构造器Dog()
*/
public void test1(){
Supplier<Dog> sup1 = new Supplier<Dog>() {
@Override
public Dog get() {
return new Dog();
}
};
Supplier<Dog> sup2 = () -> new Dog();
Supplier<Dog> sup3 = Dog::new;
}
/**
* Function中的R apply(T t)
*
*/
public void test2(){
Function<String, Dog> func1 = name -> new Dog(name);
Function<String, Dog> func2 = Dog::new;
}
/**
* 数组引用
*/
public void test3(){
Function<Integer, String[]> func1 = length -> new String[length];
Function<Integer, String[]> func2 = String[]::new;
}
}