常规方法
常规方法:先实现一个接口,声明一个该实现类的对象,再将该对象传递给函数。
改进方法:用匿名内部类的方式实现接口,再声明该接口的匿名对象传递给函数。
两种方法实现如下所示:
public class Demo01Runnable {
public static void main(String[] args) {
//常规方法
Runnable r = new RunnableImpl();
Thread t = new Thread(r);
t.start();
//匿名内部类+匿名对象
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "线程创建");
}
}).start();
}
}
Lambda表达式的标准格式:
三个部分:
- 参数
- 箭头
- 代码
格式:
(参数列表) -> {一些方法重写的代码}
使用Lambda表达式可以进一步简化表达式:
//Lambda表达式
new Thread(() -> System.out.println(Thread.currentThread().getName() + "线程创建")).start();
Lambda表达式的练习
练习一:
public interface Cook {
void makeFood();
}
public class Demo02Cook {
public static void main(String[] args) {
invokeCook(() -> System.out.println("whasup?"));
}
private static void invokeCook(Cook cook){
cook.makeFood();
}
}
练习二:
public class Demo04Calculator {
public static void main(String[] args) {
int a = 1, b = 2;
//Lambda
invokeCalc(a, b, (o1, o2) -> o1 - o2);
//匿名内部类
invokeCalc(a, b, new Calculator() {
@Override
public int calc(int a, int b) {
return a - b;
}
});
}
private static void invokeCalc(int a, int b, Calculator calculator) {
int result = calculator.calc(a, b);
System.out.println("result:" + result);
}
}
interface Calculator {
int calc(int a, int b);
}
练习三:
public class Demo03Sort {
public static void main(String[] args) {
List<Person> list = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < 20; i++) {
list.add(new Person("Person" + i, random.nextInt(100)));
}
//Lambda表达式
Collections.sort(list, (o1, o2) -> {
return o1.getAge() - o2.getAge();
});
//Lambda表达式简化
Collections.sort(list, (o1, o2) -> o1.getAge() - o2.getAge());
System.out.println("按年龄升序:");
for (Person person : list) {
System.out.println(person);
}
//匿名内部类
Collections.sort(list, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o2.getAge() - o1.getAge();
}
});
System.out.println("按年龄降序:");
for (Person person : list) {
System.out.println(person);
}
}
}
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
public String toString() {
return String.format("%-10s%-5d", name, age);
}
}
Lambda表达式的简化
public class Demo05ArrayList {
public static void main(String[] args) {
//匿名内部类
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "线程创建");
}
});
//Lambda
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "线程创建");
}).start();
//Lambda简化
new Thread(() -> System.out.println(Thread.currentThread().getName() + "线程创建")).start();
}
}
注意事项
- 使用Lambda必须具有接口或抽象类,且要求接口中有且只有一个抽象方法
- 使用Lambda必须具有上下文推断,也就是方法的参数或局部变量类型必须为Lambda对应的接口类型,才能使用Lambda作为接口的实例
备注:有且只有一个抽象方法的接口,称为“函数式接口”