JDK8的特性
1. Lambda表达式 2. 函数式接口 3. 方法引用。 4. Stream流 5. 日期时间类
1.Lambda表达式
1.1 lambda的由来
/**
* @Description:
* @Author: Zhou
* @CreateTime: 2023/6/13 16:07
*/
public class Test01 {
public static void main(String[] args) {
//开启一个线程 该构造函数需要传递一个Runnable类型的接口参数
Thread thread = new Thread(new My());
//开启线程
thread.start();
//匿名内部类
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("通过匿名内部类实现线程任务");
}
});
//开启线程
thread1.start();
}
}
class My implements Runnable{
@Override
public void run() {
System.out.println("使用实现类来完成线程任务");
}
}
分析:
Thread类需要一个Runnable接口作为参数,其中的抽象方法run方法是用来指定线程任务内容的核心方法,并且Runnable接口中有且只有一个抽象方法
为了指定run方法体,不得不需要Runnable的实现类
为了省去定义一个Runnable 的实现类,不得不使用匿名内部类
必须覆盖重写抽象的run方法,所有的方法名称,方法参数,方法返回值不得不都重写一遍,而且不能出错,
而实际上,我们只在乎方法体中的代码.
我们可以使用lambda表达式来完成上面的功能。
1.2 lambda表达式初体验
//lambda表达式
Runnable runnable = ()->{
System.out.println("lambda表达式完成线程任务");
};
//将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
Thread thread2 = new Thread(runnable);
//开启线程
thread2.start();
1.3 lambda表达式的语法
lambda省去了面向对象的条条框框,lambda的标注格式有3个部分组成:
Lambda表达式的基础语法
Lambda是一个匿名函数 一般关注的是以下两个重点
参数列表 方法体
组成Lambda表达式的三要素:参数,箭头,代码块
(参数列表)->{}
():用来描述参数列表 如果有多个参数,参数之间用逗号隔开;如果没有参数,留空即可
->: Lambda运算符 连接符 连接的是参数以及方法体
{}:用来描述方法体 有时可以省略
1.4 练习
-
Lambda表达式的使用前提 ①、有一个接口 ②、接口中有且仅有一个抽象方法
(1)抽象方法无参无返回值
/**
* @Description:
* @Author: Zhou
* @CreateTime: 2023/6/13 17:04
*/
public class Test02 {
public static void main(String[] args) {
//主函数调用fun方法。第一种:创建UserService接口的实现类,并且创建该类的实现对象
//创建UserServiceImpl的实现对象
UserServiceImpl userService = new UserServiceImpl();
userService.show();
//第二种:匿名内部类的方式
UserService userService1 = new UserService() {
@Override
public void show() {
System.out.println("这是匿名内部类的show方法的实现");
}
};
fun(userService1);
//第三种:lambda表达式--该接口必须为函数式接口
UserService userService2=()->{
System.out.println("这是lambda表达式的show方法");
};
fun(userService2);
}
public static void fun(UserService userService){
userService.show();
}
}
@FunctionalInterface
interface UserService{
/**
* 函数式接口(FunctionalInterface)-->里面有且只有一个抽象方法。
* 只有这种接口才能使用lambda表达式。
*/
public void show();
}
class UserServiceImpl implements UserService{
@Override
public void show() {
System.out.println("这是USerService的实现类的show方法");
}
}
(2)抽象方法有参有返回值
Collections 类是 Java 提供的一个操作 Set、List 和 Map 等集合的工具类。Collections 类提供了许多操作集合的静态方法,借助这些静态方法可以实现集合元素的排序、查找替换和复制等操作.
Collections 提供了如下方法用于对 List 集合元素进行排序。
void reverse(List list):对指定 List 集合元素进行逆向排序。
void shuffle(List list):对 List 集合元素进行随机排序(shuffle 方法模拟了“洗牌”动作)。
void sort(List list):根据元素的自然顺序对指定 List 集合的元素按升序进行排序。
void sort(List list, Comparator c):根据指定 Comparator 产生的顺序对 List 集合元素进行排序。
void swap(List list, int i, int j):将指定 List 集合中的 i 处元素和 j 处元素进行交换。
void rotate(List list, int distance):当 distance 为正数时,将 list 集合的后 distance 个元素“整体”移到前面;当 distance 为负数时,将 list 集合的前 distance 个元素“整体”移到后面。该方法不会改变集合的长度。
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* @Description:
* @Author: Zhou
* @CreateTime: 2023/6/13 18:31
*/
public class Test03 {
public static void main(String[] args) {
List<Person> personList = new ArrayList<>();
personList.add(new Person("张三",55));
personList.add(new Person("李四",5));
personList.add(new Person("王五",65));
personList.add(new Person("赵六",15));
personList.add(new Person("刘强",45));
//对集合中的元素按照年龄排序,由小到大
System.out.println(personList);
//Collections:集合工具类,--匿名内部类
// Comparator<Person> comparator = new Comparator<Person>() {
// @Override//如果是0表示相同 大于0表示o1大于o2
// public int compare(Person o1, Person o2) {
// return o1.getAge()-o2.getAge();
// }
// };
// Collections.sort(personList,comparator);
// System.out.println(personList);
//lambda表达式就是对函数式接口中的抽象方法的简写
Collections.sort(personList,(o1, o2) -> {
return o1.getAge()- o2.getAge();
});
System.out.println(personList);
}
}
class Person{
private String name;
private Integer age;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public Person() {
}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
(3)抽象方法有参无返回值
/**
* @Description:
* @Author: Zhou
* @CreateTime: 2023/6/13 20:34
*/
public class Test04 {
public static void main(String[] args) {
//匿名内部类
EmpService empService=new EmpService() {
@Override
public void eat(String food) {
System.out.println("烧烤");
}
};
fun(empService);
//lambda表达式
EmpService empService1=(f)->{
System.out.println("爆炒鸡");
};
fun(empService1);
}
public static void fun(EmpService empService){
empService.eat("龙虾");
}
}
interface EmpService{
public void eat(String food);
}
1.5 Lambda表达式的省略写法
在lambda表达式的标准写法基础上,可以使用省略写法规则为: ①、小括号内的参数类型可以省略。但是有多个参数的情况下,不能只省略一个 ②、如果小括号内有且仅有一个参数,那么小括号可以省略 ③、如果代码块的语句有且仅有一条,可以同时省略大括号、return关键字以及分号。
/**
* @Description:
* @Author: Zhou
* @CreateTime: 2023/6/13 20:47
*/
public class Test05 {
public static void main(String[] args) {
Us u=a -> System.out.println("你好明天:"+a);
fun(u);
// Us2 us2=a -> {return a*2;};
//默认lambda表达式就会把最后一条语句作为返回结果。
// Us2 us2=a -> a*2;
// fun02(us2);
fun02(a -> a*2);
}
public static void fun(Us us){
us.show(15);
}
public static void fun02(Us2 us2){
System.out.println(us2.print(25));
}
}
interface Us{
public void show(int a);
}
interface Us2{
public int print(int a);
}
1.6 Lambda表达式使用的前提
Lambda表达式的语法是非常简洁的,但是Lambda表达式不是随便使用的,使用时有几个条件要特别注意
-
方法的参数或局部变量类型必须为接口才能使用Lambda
-
接口中有且仅有一个抽象方法(@FunctionalInterface)
后面我们使用lambda表达式主要核心使用再Stream流中。
2.内置函数式接口
要想使用lambda表达式它的前提就是必须是函数式接口。
2.1 内置函数式接口的由来
/**
* @Description:
* @Author: Zhou
* @CreateTime: 2023/6/14 14:04
*/
public class Test {
public static void main(String[] args) {
Operation o=arr -> {
int sum=0;
for (int s : arr) {
sum+=s;
}
return sum;
};
fun(o);
}
public static void fun(Operation operation){
int[] arr={1,2,3,4};
int sum= operation.getSum(arr);
System.out.println("数组的和:"+sum);
}
}
@FunctionalInterface
interface Operation