Lambda 是一个匿名函数,我们可以把 Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。
MyInterface接口(提供show方法):
public interface MyInterface {
void show();
}
测试类:
public class MyTest {
public static void main(String[] args) {
// Lambda 表达式,是JDK1.8之后,提供一种语法风格,你可以认为他是匿名内部类的一种进行形式,他可以作为参数进行传递
//匿名内部类
MyInterface myInterface = new MyInterface() {
@Override
public void show() {
System.out.println("这是show方法");
}
};
//针对上面的匿名内部类的写法,我们可以使用 Lambda 表达式 进行简化
MyInterface myInterface2 = () -> {
System.out.println("这是show方法");
};
}
}
public class MyTest2 {
public static void main(String[] args) {
//Lambda 表达式,的语法
//引入一个箭头符号 ->
// 箭头 -> 把 Lambda 表达式 分成左右两部分
// 箭头左边是 接口中抽象方法的 形参列表
// 箭头右边是,抽象方法的具体重写逻辑
// 匿名内部类的写法
Comparator comparator = new Comparator() {
@Override
public int compare(Integer a, Integer b) {
return a - b;
}
};
//第一步简写:
Comparator comparator2 = (Integer a, Integer b) -> {
return a - b;
};
//形参的数据类型,可以省略不写,因为有泛型可以推断出形参的数据类型
Comparator comparator3 = (a, b) -> {
return a - b;
};
//还能再简化
//如果你的重写逻辑只有一行代码,那么{} return 都可以省略不写
Comparator comparator4 = (a, b) -> a - b;
}
}
Iiterface接口:
public interface Iinterface {
int test(int num);
}
测试类:
public class MyTest2 {
public static void main(String[] args) {
Iinterface iinterface = new Iinterface() {
@Override
public int test(int num) {
return num + 10;
}
};
Lambda 表达式,简写了匿名内部类 ,如果形参只有一个 ()可以省略不写
Iinterface iinterface2 = x -> x += 10;
}
}
public class MyTest3 {
public static void main(String[] args) {
TreeSet strings = new TreeSet<>(new Comparator() {
@Override
public int compare(String a, String b) {
return 0;
}
});
TreeSet strings2 = new TreeSet<>((a, b) -> a.compareTo(b));
//可以alt+enter 选择替换成 Lmabda表达式
TreeSet strings3 = new TreeSet<>((a, b) -> a.compareTo(b));
}
}
任意函数式接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口,同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口.
下面代码加上注解就会报错:
//@FunctionalInterface 加上就报错
public interface HeHe {
void aa();
void bb();
}
函数式接口:
@FunctionalInterface //这个注解就表明了,这是一个函数式接口
public interface HaHa {
void test();
}
测试类:
public class MyTest {
public static void main(String[] args) {
//Lambda 表达式 他需要函数式接口的支持,换句话说,就是只有函数式接口,才能使用Lambda写出来
// 函数式接口:就是接口中,只有一个抽象方法,有个注解 @FunctionalInterface 可以检测该接口是不是函数式接口
HeHe heHe = new HeHe() {
@Override
public void aa() {
}
@Override
public void bb() {
}
};
HaHa haHa = new HaHa() {
@Override
public void test() {
}
};
HaHa haHa2 = () -> System.out.println("aaaa");
}
}
函数式接口 |
参数类型 |
返回类型 |
用途 |
Consumer 消费型接口 |
T |
void |
对类型为T的对象应用操 |
Supplier 供给型接口 |
无 |
T |
返回类型为T的对象,包 |
Function 函数型接口 |
T |
R |
对类型为T的对象应用操 |
Predicate |
T |
boolean |
确定类型为T的对象是否 |
其他函数式接口:
函数式接口 |
参数类型 |
返回类型 |
用途 |
BiFunction |
T U |
R |
对类型为 T, U 参数应用 |
UnaryOperator (Function的子接口) |
T |
T |
对类型为T的对象进行一 |
BinaryOperator (BiFunction的子接口) |
T T |
T |
对类型为T的对象进行二 |
BiConsumer |
T U |
void |
对类型为T, U 参数应用 |
ToIntFunction |
T |
int |
分 别 计 算 int 、 long 、 |
IntFunction |
int |
R |
参数分别为int、 long、 |
方法引用:方法引用其实是Lambda表达式的另一种写法,
当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用.
注意:实现抽象方法的参数列表,必须与方法引用方法的参数列表保持一致!
方法引用:使用操作符 “ ::” 将方法名和对象或类的名字分隔开来。
如下三种主要使用情况:对象::实例方法
类::静态方法
类::实例方法
public class MyTest {
public static void main(String[] args) {
Consumer consumer = new Consumer() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
consumer.accept("abc");
Consumer consumer2 = s -> System.out.println(s);
consumer2.accept("hello");
//你对 Consumer接口 中的 public void accept(String s) 这抽象方法的重写逻辑 System.out.println(s)
//注意观察:accept(String s) 这抽象方法,没有返回值,有一个参数
//再来观察:我们的重写逻辑
//PrintStream out = System.out;
//out.println("abc");
//调用的这个println("abc") 他的返回值类型和形参列表,跟 accept(String s) 方法的返回值类型和形参列表是一致的,如果有这种巧合就可以简写成下面的 实例对象::方法
Consumer consumer3 = System.out::println;
System.out.println("==========================");
BinaryOperator binaryOperator = new BinaryOperator() {
@Override
public Double apply(Double x, Double y) {
return Math.max(x, y);
}
};
//第一次简写
BinaryOperator binaryOperator2 = (x, y) -> Math.max(x, y);
//最终简写,因为又有巧合重写
//观察: BinaryOperator 中的 apply抽象方法,有一个返回值,有两个参数
//观察我们的重写逻辑 Math.max(x, y); 调用 的max方法,有一个返回值,有两个参数,能和apply抽象方法对应上
//最终简写,类名::静态方法
BinaryOperator binaryOperator3 = Math::max;
System.out.println("==============================================");
Comparator comparator = new Comparator() {
@Override
public int compare(String a, String b) {
//第一个参数作为了调用者,第二个参数,作为传入值
return a.compareTo(b);
}
};
//第一步简写
Comparator comparator2 = (a, b) -> a.compareTo(b);
//最终简写:第一个参数作为了调用者,第二个参数,作为传入值
Comparator comparator3 = String::compareTo;
System.out.println("=========================================");
BiFunction biFunction = new BiFunction() {
@Override
public Boolean apply(String x, String y) {
return x.equals(y);
}
};
BiFunction biFunction2 = (x, y) -> x.equals(y);
//最终简写
BiFunction biFunction3 = String::equals;
}
}
格式:ClassName::new
与函数式接口相结合,自动与函数式接口中方法兼容。可以把构造器引用赋值给定义的方法,与构造器参数列表要与接口中抽象方法的参数列表一致!
Student类:
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
测试类:
public class MyTest2 {
public static void main(String[] args) {
Supplier supplier = new Supplier() {
@Override
public Student get() {
return new Student();
}
};
Supplier supplier2 = () -> new Student();
//最终简写 观察:构造方法,和接口中的抽象方法get() 方法的返回值和形参列表能对应上,就可以用构造引用简写
Supplier supplier3 = Student::new;
System.out.println("==================================================");
BiFunction biFunction = new BiFunction() {
@Override
public Student apply(String name, Integer age) {
return new Student(name, age);
}
};
Student wangwu = biFunction.apply("wangwu", 25);
//第一次简写
BiFunction biFunction2 = (name, age) -> new Student(name, age);
Student s0 = biFunction2.apply("lisi", 24);
//最终简写:
BiFunction biFunction3 = Student::new;
Student s = biFunction3.apply("张三", 23);
}
}