我们要使用JDK8新特性,请务必调试好IDEA这两个配置。
(一)匿名内部类存在的问题分析
package com.lambda;
/**
* @Author:kaiyang.cui
* @Package:com.lambda
* @Project:jdk8
* @name:Demo01
* @Date:2023/4/2 下午2:59
* @Filename:Demo01
* @Description:匿名内部类存在的问题
* @Version:1.0
*/
public class Demo01 {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("新线程中执行的代码:" + Thread.currentThread().getName());
}
}).start();
System.out.println("主线程中的代码:"+ Thread.currentThread().getName());
}
}
Result:
主线程中的代码:main
新线程中执行的代码:Thread-0
(二)Lambda表达式的使用
Lambda表达式是一个匿名函数,可以理解为一段可以传递的代码
package com.lambda;
/**
* @Author:kaiyang.cui
* @Package:com.lambda
* @Project:jdk8
* @name:Demo01
* @Date:2023/4/2 下午2:59
* @Filename:Demo01
* @Description:使用Lambda表达式优化线程问题
* @Version:1.0
*/
public class Demo01 {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("新线程中执行的代码:" + Thread.currentThread().getName());
}
}).start();
System.out.println("主线程中的代码:"+ Thread.currentThread().getName());
new Thread(() -> {
System.out.println("新线程Lambda表达式..." + Thread.currentThread().getName());
}).start();
}
}
Result:
主线程中的代码:main
新线程中执行的代码:Thread-0
新线程Lambda表达式...Thread-1
Lambda表达式的优点:
简化了匿名内部类的使用,语法更加简单。
匿名内部类语法冗余,体验了Lambda表达式后,发现Lambda表达式是简化匿名内部类的一种方式。
Lambda的语法规则
~~public~~ ~~static~~ ~~void~~ ~~main~~(String[] args){}
Lambda表达式不关注权限控制符
,不关注表述static
,不关注方法的返回类型
,更不会关注方法的名称
, 针对的是参数列表和方法体。
Lambda会讲关注的部分做一个变形: 由原来的
(String[] args){}
变为:
(String[] args) -> {}
Lambda 表达式省去了面向对象的条条框框。Lambda 的标准格式由3个部分组成
(参数类型 参数名称) -> {
}
说明:
(参数类型 参数名称)
方法体{}
代码体->
: 箭头,分割参数列表和方法体
2.1 Lambda 练习1 【无参无返回值】
package com.lambda.service;
/**
* @Author:kaiyang.cui
* @Package:com.lambda.service
* @Project:jdk8
* @name:UserService
* @Date:2023/4/2 下午3:43
* @Filename:UserService
* @Description:UserService
* @Version:1.0
*/
public interface UserService {
void show();
}
使用匿名内部类调用接口
package com.lambda;
import com.lambda.service.UserService;
/**
* @Author:kaiyang.cui
* @Package:com.lambda
* @Project:jdk8
* @name:Demo01
* @Date:2023/4/2 下午2:59
* @Filename:Demo01
* @Description:参数中传递接口,应该使用内部类的方式调用。
* @Version:1.0
*/
public class Demo02 {
public static void main(String[] args) {
/**
* 参数是接口,接口不能实例化,只能通过内部类的方式调用
*/
goShow(new UserService() {
@Override
public void show() {
System.out.println("show 方法被调用");
}
});
}
public static void goShow(UserService userService){
userService.show();
}
}
使用lambda优雅的完成调用:
package com.lambda;
import com.lambda.service.UserService;
/**
* @Author:kaiyang.cui
* @Package:com.lambda
* @Project:jdk8
* @name:Demo01
* @Date:2023/4/2 下午2:59
* @Filename:Demo01
* @Description:参数中传递接口,应该使用内部类的方式调用,但是不优雅,使用Lambda优雅的调用
* @Version:1.0
*/
public class Demo03 {
public static void main(String[] args) {
goShow(()->{
System.out.println("lambda show 方法被调用");
});
}
public static void goShow(UserService userService){
userService.show();
}
}
2.2 Lambda 练习2 【有参有返回值】
我们在List集合中保存多个Person对象,然后对这些对象根据age做升序操作。
使用内部类实现递增排序
package com.lambda.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author:kaiyang.cui
* @Package:com.lambda.domain
* @Project:jdk8
* @name:Person
* @Date:2023/4/2 下午3:58
* @Filename:Person
* @Description:Person实体类
* @Version:1.0
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {
private String name;
private Integer age;
private Integer height;
}
package com.lambda;
import com.lambda.domain.Person;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
/**
* @Author:kaiyang.cui
* @Package:com.lambda
* @Project:jdk8
* @name:Demo01
* @Date:2023/4/2 下午2:59
* @Filename:Demo01
* @Description:排序问题
* @Version:1.0
*/
public class Demo04 {
public static void main(String[] args) {
List<Person> list = new ArrayList<>();
list.add(new Person("周杰伦4", 24, 184));
list.add(new Person("周杰伦1", 21, 181));
list.add(new Person("周杰伦5", 25, 185));
list.add(new Person("周杰伦3", 23, 183));
list.add(new Person("周杰伦2", 22, 182));
// 排序
Collections.sort(list, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge() - o2.getAge();
}
});
for (Person person : list) {
System.out.println("person = " + person);
}
}
}
Result:
person = Person(name=周杰伦1, age=21, height=181)
person = Person(name=周杰伦2, age=22, height=182)
person = Person(name=周杰伦3, age=23, height=183)
person = Person(name=周杰伦4, age=24, height=184)
person = Person(name=周杰伦5, age=25, height=185)
优雅的使用lambda排序
我们发现sort方法的第二个参数是Comparator
接口的匿名内部类,且执行的方法和返回值,那么我们可以改写为Lambda表达式。
package com.lambda;
import com.lambda.domain.Person;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* @Author:kaiyang.cui
* @Package:com.lambda
* @Project:jdk8
* @name:Demo01
* @Date:2023/4/2 下午2:59
* @Filename:Demo01
* @Description:排序问题-Lambda解决
* @Version:1.0
*/
public class Demo05 {
public static void main(String[] args) {
List<Person> list = new ArrayList<>();
list.add(new Person("周杰伦4", 24, 184));
list.add(new Person("周杰伦1", 21, 181));
list.add(new Person("周杰伦5", 25, 185));
list.add(new Person("周杰伦3", 23, 183));
list.add(new Person("周杰伦2", 22, 182));
Collections.sort(list,(Person o1,Person o2) -> {
return o1.getAge() - o2.getAge();
});
for (Person person : list) {
System.out.println("person = " + person);
}
}
}
Result:
person = Person(name=周杰伦1, age=21, height=181)
person = Person(name=周杰伦2, age=22, height=182)
person = Person(name=周杰伦3, age=23, height=183)
person = Person(name=周杰伦4, age=24, height=184)
person = Person(name=周杰伦5, age=25, height=185)
FunctionalInterface 注解说明
public interface UserService {
void show();
void show2();
}
在接口中再定一个方法,我们神奇的发现,报错了,
我们使用UserService
接口必须得有一个抽象方法。
怎么保证接口中只有一个抽象方法呢?
@FunctionalInterface
@FunctionalInterface注解的作用就是保证注解所修饰的抽象方法只能定义一个抽象方法!!!!