我们先看以下线程的代码:
public class Test {
public static void main(String[] args) {
// 匿名内部类
Runnable task = new Runnable() {
@Override
public void run() { // 覆盖重写抽象方法
System.out.println("多线程任务执行!");
}
};
new Thread(task).start(); // 启动线程
}
}
使用Lambda表达式后的代码:
public class Test {
public static void main(String[] args) {
//Lambda表达式
new Thread(() -> System.out.println("多线程任务执行!")).start(); // 启动线程
}
}
两者执行的结果一样,可见Lambda表达式简化了非常多的代码。
我们在使用匿名内部类时,省去了类的定义,但是仍然存在代码冗余。
而Lambda表达式则进一步省略了匿名内部类的相关代码。
Lambda标准格式。
一些参数一个箭头一段代码
Lambda表达式的标准格式为:
(参数类型 参数名称) ‐> { 代码语句 }
格式说明:
小括号内的语法与传统方法参数列表一致:无参数则留空;多个参数则用逗号分隔。-> 是新引入的语法格式,代表指向动作。大括号内的语法与传统方法体要求基本一致。
练习:(无参)
定义一个接口Fly:
public interface Fly {
public void fly();
}
测试类:
public class Test {
public static void main(String[] args) {
//未使用Lambda
canFly(new Fly() {
@Override
public void fly() {
System.out.println("我飞了");
}
});
//使用Lambda
canFly(() -> System.out.println("我飞了"));
}
public static void canFly(Fly flyy){
flyy.fly();
}
}
Lambda的有参数和返回值:
题目需求:
使用数组存储多个Person对象,对数组中的Person对象使用Arrays的sort方法通过年龄进行升序排序
定义Person类:
public class Person {
private String name;
private int age;
public Person(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;
}
}
传统写法:
import java.util.Arrays;
import java.util.Comparator;
public class Test {
public static void main(String[] args) {
// 本来年龄乱序的对象数组
Person[] array = {
new Person("古力娜扎", 19),
new Person("迪丽热巴", 18),
new Person("马尔扎哈", 20) };
// 匿名内部类
Comparator comp = new Comparator() {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge() - o2.getAge();
}
};
Arrays.sort(array, comp); // 第二个参数为排序规则,即Comparator接口实例
for (Person person : array) {
System.out.println(person);
}
}
}
代码分析:
为了排序, Arrays.sort 方法需要排序规则,即 Comparator 接口的实例,抽象方法 compare 是关键;为了指定 compare 的方法体,不得不需要 Comparator 接口的实现类;为了省去定义一个 ComparatorImpl 实现类的麻烦,不得不使用匿名内部类;必须覆盖重写抽象 compare 方法,所以方法名称、方法参数、方法返回值不得不再写一遍,且不能写错;实际上,只有参数和方法体才是关键。
因此,使用Lambda表达式需要传入两个参数,分别为Person o1, Person o2;返回值则是o1.getAge() ‐ o1.getAge();
Lambda表达式为:
import java.util.Arrays;
import java.util.Comparator;
public class Test {
public static void main(String[] args) {
// 本来年龄乱序的对象数组
Person[] array = {
new Person("古力娜扎", 19),
new Person("迪丽热巴", 18),
new Person("马尔扎哈", 20) };
//Lambda表达式
Arrays.sort(array,(Person o1, Person o2) -> {
return o1.getAge() - o2.getAge();
});
for (Person person : array) {
System.out.println(person);
}
}
}
Lambda的使用前提:
- 使用Lambda必须具有接口,且要求接口中有且仅有一个抽象方法。 无论是JDK内置的 Runnable 、 Comparator 接口还是自定义的接口,只有当接口中的抽象方法存在且唯一 时,才可以使用Lambda。使用Lambda必须具有上下文推断。 也就是方法的参数或局部变量类型必须为Lambda对应的接口类型,才能使用Lambda作为该接口的实例。
备注:有且仅有一个抽象方法的接口,称为“函数式接口



