一、Lamdba 表达式与函数式接口
1.1 Lamdba 表达式与函数式接口
1.1.1 Lambda 表达式概述
- Lambda 表达式是 Java 8 引入的一个新特性
- Lambda 表达式可以被视为匿名函数
- 允许在需要函数的地方以更简洁的方法定义功能
- Lambda 表达式可以完成简洁的函数定义
- Stream API 中大量使用了 Lambda 表达式,可以使用 Lambda 表达式对集合进行操作
- Lambda 表达式允许你将函数作为参数传递传递给其它函数,或将函数组合在一起形成新的函数
1.1.2 使用 Lambda 表达式实现接口
- 首先定义一个接口
interface MyInterface {
int sum(int x,int y);
}
public class Main {
public static void main(String[] args) {
}
}
- 使用 Lambda 表达式实现接口
interface MyInterface {
int sum(int x,int y);
}
public class Main {
public static void main(String[] args) {
MyInterface myInterface = (int x,int y) ->{
return x+y;
};
System.out.println(myInterface.sum(1, 2));
}
}
1.1.3 函数式接口概述
- 接口中只有一个未实现的方法,被称为函数式接口
- 只要是函数式接口,就可以使用 Lambda 表达式
- 在 Java 中可以使用
@FunctionalInterface
来表示函数式接口
1.1.4 Lambda 表达式简写形式
1、参数类型可以不写,只写参数名
MyInterface myInterface = (x,y) ->{
return x+y;
};
2、参数变量名也可以随意定义,但是参数数量一定要一致
MyInterface myInterface = (i,j) ->{
return x+y;
};
3、如果只有一个参数,可以不写小括号,但没有参数一定要写小括号
MyInterface myInterface1 = i ->{
return i;
};
MyInterface myInterface2 = () ->{
return 1;
};
4、方法体如果只有一句话,可以省略 {}
MyInterface myInterface = i -> return i;
1.2 Function PAI 函数式接口
1.2.1 Function 函数式接口概述
- Function API 是 Java 函数式接口的底层定义
- Function API 包括了许多不同种类类型的函数式接口
- 以支持各种函数式编程风格和操作
1.2.2 Function API 不同类型的函数式接口
以下是 Function API 内置的函数式接口
- 其中标红的四个接口
Consumer、Function、Perdicate、Supplier
是四个常见的函数式接口 - 它们四个代表了函数式编程中的不同类型
- Consumer 接口 表示接受一个参数并无返回值操作,被称为消费者
- Function 接口 表示接受一个参数并返回一个结果的函数,通常被视为常用的函数接口
- Perdicate 接口表示接受一个参数并返回一个布尔值,被称为断言
- Supplier 接口表示无参数并返回一个结果,并成为提供者
1.2.3 使用 Function 不同类型的接口完成小案例
小案例
1.使用 Supplier 生成一个字符串数据
2.使用 Predicate 验证输入字符串是否为数字
3.使用 Function 转换数据,将字符串转为数字
4.使用 Consumer 判断数字是奇数还是偶数
5.将上面一系列操作串联起来
每个函数式接口当中都有一个方法,需要调用,如果不清楚方法名,可找到这个接口自行查看
1、使用 Supplier 生成一个字符串数据
package org.example;
import java.util.function.Supplier;
public class FunctionDemo {
public static void main(String[] args) {
//生成一个字符串数据
Supplier<String> supplier=() -> "42";
System.out.println(supplier.get());
}
}
2、使用 Predicate 验证输入字符串是否为数字
package org.example;
import java.util.function.Predicate;
import java.util.function.Supplier;
public class FunctionDemo {
public static void main(String[] args) {
//验证输入字符串是否为数字
Predicate<String> predicate=str -> str.matches("-?\\d+(\\.\\d+)?");
System.out.println(predicate.test("435"));
System.out.println(predicate.test("435a"));
}
}
3、转换数据,将字符串转为数字
package org.example;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
public class FunctionDemo {
public static void main(String[] args) {
//转换数据,将字符串转为数字
Function<String,Integer> function= Integer::parseInt;
Integer num = function.apply("435");
System.out.println(num);
}
}
4、判断数字是奇数还是偶数
package org.example;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
public class FunctionDemo {
public static void main(String[] args) {
//判断数字是奇数还是偶数
Consumer<Integer> consumer=integer -> {
if (integer %2 == 0){
System.out.println("偶数"+integer);
}else {
System.out.println("奇数"+integer);
}
};
consumer.accept(44);
}
}
5、将这些操作串联起来,实现判断 Supplier 生成的字符串是奇数还是偶数
package org.example;
import java.util.Scanner;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
public class FunctionDemo {
public static void main(String[] args) {
//生成一个字符串数据
Supplier<String> supplier=() -> "42";
//验证输入字符串是否为数字
Predicate<String> predicate=str -> str.matches("-?\\d+(\\.\\d+)?");
//转换数据,将字符串转为数字
Function<String,Integer> function= Integer::parseInt;
//判断数字是奇数还是偶数
Consumer<Integer> consumer=integer -> {
if (integer %2 == 0){
System.out.println("偶数"+integer);
}else {
System.out.println("奇数"+integer);
}
};
//将这些操作串联起来,实现判断 Supplier 生成的字符串是奇数还是偶数
if(predicate.test(supplier.get())){
consumer.accept(function.apply(supplier.get()));
}else {
System.out.println("非法数字");
}
}
}
6、也可以将他们全部组合成一个方法
package org.example;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
public class FunctionMethod {
public static void main(String[] args) {
myMethod(() -> "4aaa",
str -> str.matches("-?\\d+(\\.\\d+)?"),
Integer::parseInt,
integer -> {
if (integer %2 == 0){
System.out.println("偶数"+integer);
}else {
System.out.println("奇数"+integer);
}
});
}
private static void myMethod(
Supplier<String> supplier,
Predicate<String> predicate,
Function<String,Integer> function,
Consumer<Integer> consumer
){
if(predicate.test(supplier.get())){
consumer.accept(function.apply(supplier.get()));
}else {
System.out.println("非法数字");
}
}
}
1.3 Stream API
1.3.1 Stream API 概述
- Stream API 主要用于处理集合数据的流式操作
- Stream API 提供了一些列的操作方法,如过滤、排序、映射、聚合等
- Stream API 可以从各种数据源创建流,如集合、数组、文件等
- 它的内部采用了并行处理机制,在处理大数据集时具有较高的性能优势
1.3.2 Stream 流的简介
-
Stream被翻译为流,它的工作过程像将一瓶水导入有很多过滤阀的管道一样,水每经过一个过滤阀,便被操作一次,比如过滤,转换等,最后管道的另外一头有一个容器负责接收剩下的水。
-
就类似于将数据导入一个管道,一遍遍的过滤,最后形成一个最终需要的数据,然后接收结果
-
将数据导入一个过滤的导管中被称为创建流
-
将数据一遍遍的过滤,被称为中间操作,我们可以定义很多种中间操作
-
数据过滤成想要的结果时,需要进行 终止操作
-
然后最后再接收结果
-
这些操作就称之为流式操作
-
而流的三大部分主要分为
- 创建数据流
- N 个中间操作
- 1 个终止操作
-
因为流式操作是可以并发的,所以所有并发流的操作都是无状态数据
- 数据状态只在函数内有效
- 不溢出至函数外
1.3.3 Stream API 的基本使用
以下是一个 Stream API 的小案例,用于筛选出集合中的偶数
然后将偶数转为字符串,遍历出来进行输出
package org.example;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamAPI {
public static void main(String[] args) {
// 创建一个整数列表
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 使用 Stream API 进行操作
numbers.stream()
// 筛选偶数
.filter(number -> number % 2 == 0)
// 排序
.sorted()
// 映射为字符串
.map(String::valueOf)
// 收集结果
.collect(Collectors.toList())
.forEach(System.out::println);
}
}
-
**通过 numbers.stream() 方法将列表转换为 Stream,这个步骤为创建数据流 **
-
使用 filter() 方法筛选出偶数,为中间操作
-
使用 sorted() 方法对筛选后的结果进行排序,为中间操作
-
使用 mapToObj() 方法将流中的整数映射为字符串,为中间操作
-
使用 collect(Collectors.toList()) 方法将映射后的结果收集到一个新的列表中,为中间操作
-
最后,使用 forEach() 方法遍历并打印收集后的结果,为终止操作
-
判断是否是中间操作,还是终止操作
- 可以直接点开类查看注释
- 中间操作一般都有返回值
- 终止操作一般是没有返回值的,也可以快速判断
-
**通过 numbers.stream() 方法将列表转换为 Stream,这个步骤为创建数据流 **
-
使用 filter() 方法筛选出偶数,为中间操作
-
使用 sorted() 方法对筛选后的结果进行排序,为中间操作
-
使用 mapToObj() 方法将流中的整数映射为字符串,为中间操作
-
使用 collect(Collectors.toList()) 方法将映射后的结果收集到一个新的列表中,为中间操作
-
最后,使用 forEach() 方法遍历并打印收集后的结果,为终止操作
-
判断是否是中间操作,还是终止操作
- 可以直接点开类查看注释
- 中间操作一般都有返回值
- 终止操作一般是没有返回值的,也可以快速判断