目录
一、概述
定义:有且仅有一个抽象方法的接口
-
Java中函数式编程体现:Lambda表达式
-
函数式接口就是可以适用于Lambda使用的接口
-
只有确保接口中仅有一个抽象方法,Java中的Lambda才能顺利地进行推导
-
如何检测一个接口是不是函数式接口?
-
@Functionallnterface
-
放在 接口定义的上方:如果接口是函数式接口,编译通过;如果不是,编译失败
注意:
我们自己定义函数式接口的时候,@Functionallnterface是可以选的,就算我们不写这个注解,只要保证满足函数式接口定义的条件,也照样是函数式接口。但是,建议加上该注解,虽然这不是强制性的,但使用它可以避免无意中添加额外的方法,从而破坏函数式接口的特性。
核心概念
函数式接口:具有且仅有一个抽象方法的接口。
Lambda表达式:一种匿名函数,可以用来替代只有单一方法的类的实例化。
方法引用:如果Lambda表达式只是简单地引用已有方法,那么可以用方法引用代替Lambda表达式。
二、 函数式接口作为方法的参数
需求
-
定义一个类(RunnableDemo),在类中提供两个方法
-
一个方法是:startThread(Runnable r) 方法参数Runnabler是一个函数式接口
-
一个方法是主方法,在主方法中调用startThread方法
-
如果方法的参数是一个函数式接口,我们可以用Lambda表达式作为参数传递
startThread(()->System.out.println(Thread.currentThread().getName()+“线程启动了”));
public class RunnableDemo {
public static void main(String[] args) {
// Lambda表达式作为参数传递
startThread(()-> System.out.println(Thread.currentThread().getName()+"线程启动了"));
}
private static void startThread(Runnable r){
new Thread(r).start();
}
}
三、函数式接口作为方法的返回值
需求
-
定义一个类(ComparatorDemo),在类中提供两个方法
-
一个方法是:Comparator< String > getComparator() 方法返回值Comparator是一个函数式接口
-
一个方法是主方法,在主方法中调用getComparator方法
-
如果一个方法的返回值是一个函数式接口,我们可以把一个Lambda表达式作为结果返回
private static Comparator<String> getComparator() {
// 定义了一个接受两个参数 s1 和 s2 的函数,这两个参数都是字符串类型。计算 s1 的长度减去 s2 的长度,并返回结果
return (s1, s2) -> s1.length() - s2.length();
}
package com.geeksss.excel.model;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
/**
* ComparatorDemo 使用自定义比较器对字符串列表进行排序。
*/
public class ComparatorDemo {
/**
* 主函数执行字符串列表的排序操作。
* @param args 命令行参数,未使用。
*/
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("cccc");
list.add("aa");
list.add("b");
list.add("ddd");
System.out.println("排序前" + list);
// 使用自定义比较器对列表进行排序。
Collections.sort(list, getComparator());
System.out.println("排序后" + list);
}
/**
* 使用Lambda表达式创建并返回Comparator实例
* 获取一个比较器实例,该比较器按字符串长度进行排序。
*
* Lambda表达式: (s1, s2) -> s1.length() - s2.length()
* 这个表达式定义了一个比较规则,根据字符串的长度进行比较
* 当s1.length() > s2.length(),返回正值,表示s1在排序中应该位于s2之后,s1比s2长
* 当s1.length() < s2.length(),返回负值,表示s1在排序中应该位于s2之前,s1比s2短
* 当s1.length() == s2.length(),返回0,表示两个字符串长度相等,保持原顺序,s1与s2一样长
*
* 方法的返回值是一个函数式接口,把一个Lambda表达式作为返回结果
* @return 返回一个 Comparator 实例,用于按照字符串长度进行排序。
*/
private static Comparator<String> getComparator() {
// 使用 Lambda 表达式定义比较逻辑:按字符串长度进行比较。
// 使用匿名内部类实现
// return new Comparator<String>() {
// @Override
// public int compare(String s1, String s2) {
// return s1.length()-s2.length();
// }
// };
// Lambda 表达式写法,等效于上述匿名内部类实现。
return (s1, s2) -> s1.length() - s2.length();
}
}
排序前[cccc, aaaa, b, ddd] 排序后[b, ddd, cccc, aaaa]
四、 常用的函数式接口
Java 8在java.util.function包下预定义了大量的函数式接口供我们使用,重点学习下面4个接口
简单总结
-
Consumer<T>:接收一个参数,但没有返回值。
-
常用于遍历数据结构,执行副作用操作,如打印或更新状态
-
-
Supplier<T>:不接收参数,返回一个结果。
-
可以用于创建延迟初始化的对象,或获取数据源的值
-
-
Function<T, R>:接收一个参数并返回一个结果。
-
可以用于数据转换或映射
-
-
Predicate<T>:接收一个参数并返回一个布尔值。
-
通常用于数据过滤
-
简单示例
import java.util.function.*;
public class FunctionalInterfaceExample {
public static void main(String[] args) {
// Consumer 示例
Consumer<String> printUpperCase = System.out::println;
printUpperCase.accept("HELLO"); // 输出 HELLO
// Supplier 示例
Supplier<Double> randomSupplier = Math::random;
System.out.println(randomSupplier.get()); // 输出一个随机数
// Function 示例
Function<String, Integer> stringToInt = Integer::parseInt;
System.out.println(stringToInt.apply("123")); // 输出 123
// Predicate 示例
Predicate<Integer> isEven = x -> x % 2 == 0;
System.out.println(isEven.test(4)); // 输出 true
}
}
4.1 Consumer接口
Consumer是一个消费型接口,它接受一个参数但不返回任何值。它常用于对集合中的元素执行某种操作,如打印或修改数据。
Consumer< T >:包含两个方法
-
void accept(T t):对给定的参数执行此操作
-
default Consumer < T > andThen(Consumer after):返回一个组合的Consumer,依次执行此操作,然后执行after操作
-
Consumer< T >接口也被称为消费型接口,它消费的数据类型由泛型指定
简单案例
package com.geeksss.excel.model;
import java.util.function.Consumer;
/**
* 消费者示例类,使用Consumer接口处理字符串。
*/
public class ConsumerDemo {
public static void main(String[] args) {
// 单个消费者处理字符串
operatorString("张三", (s) -> System.out.println(s));
// 两个消费者依次处理字符串
operatorString("张三", (s) -> System.out.println(s), (s) -> System.out.println(new StringBuilder(s).reverse().toString()));
}
/**
* 接受一个字符串并应用一个消费者。
* @param name 要处理的字符串
* @param con 字符串的消费者
*/
// 定义一个方法,消费一个字符串数据
private static void operatorString(String name, Consumer<String> con) {
con.accept(name);
}
/**
* 接受一个字符串并依次应用两个消费者。
* @param name 要处理的字符串
* @param con1 第一个字符串消费者
* @param con2 第二个字符串消费者
*/
// 定义一个方法,用不同的方式消费同一个字符串两次
private static void operatorString(String name, Consumer<String> con1, Consumer<String> con2) {
// 通过andThen方法将两个消费者串联起来,形成一个消费链
// 返回一个组合的Consumer
con1.andThen(con2).accept(name);
}
// 张三
// 张三
// 三张
}
自我练习
-
String[] strArray = {“张三,30”, “李四,21”, “王五,18”};
-
字符串数组中有多条信息,按照格式:
-
把打印姓名的动作,作为第一个Consumer接口的Lambda实例
-
把打印年龄的动作,作为第二个Consumer接口的Lambda实例
-
将两个Consumer接口按照顺序组合到一起使用
-
package com.geeksss.excel.model;
import java.util.Arrays;
import java.util.function.Consumer;
/**
* @author zhumq
* @date 2024/7/30 22:27
*/
public class ConsumerTest {
public static void main(String[] args) {
String[] strArray = {"张三,30", "李四,21", "王五,18"};
// 使用operatorString方法处理字符串数组,分别输出原字符串和分割后的数组
operatorString(strArray, (s) -> System.out.println(s), (s) -> System.out.println(Arrays.toString(s.split(","))));
}
/**
* 对字符串数组中的每个元素应用两个消费者操作:首先执行第一个消费者,然后执行第二个消费者。
*
* @param strArray 字符串数组
* @param con1 第一个字符串消费者
* @param con2 第二个字符串消费者
*/
public static void operatorString(String[] strArray, Consumer<String> con1, Consumer<String> con2) {
for (String str : strArray) {
// 通过andThen方法将两个消费者串联起来,形成一个消费链
con1.andThen(con2).accept(str);
}
}
// 张三,30
// [张三, 30]
// 李四,21
// [李四, 21]
// 王五,18
// [王五, 18]
}
实际应用场景
多线程处理
Consumer接口在多线程环境中非常有用,可以用于并行处理数据集中的每个元素,例如在异步任务中处理数据。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
public class MultiThreadedProcessing {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(4);
Consumer<String> processTask = task -> {
System.out.println("Processing task '" + task + "' on thread " + Thread.currentThread().getName());
// 这里可以是任务的具体处理逻辑
};
for (int i = 0; i < 10; i++) {
String task = "Task-" + i;
executor.submit(() -> processTask.accept(task));
}
executor.shutdown();
}
}
4.2 Supplier<T>接口
Supplier< T >:包含一个无参的方法
-
T get():获得结果
-
该方法不需要参数,他会按照某种实现逻辑返回一个数据(由Lambda表达式实现)
-
Supplier< T >接口也被称为生产型接口,如果我们指定了接口的泛型是什么类型,那么接口中的get方法就会产生什么类型的数据供我们使用
简单案例
import java.util.function.Supplier;
public class SupplierDemo {
public static void main(String[] args) {
String s = getString(()->"张三");
int i = getInteger(()->18);
System.out.println(s+","+i);
}
//定义一个方法,返回一个字符串数据
private static String getString(Supplier<String> sup){
return sup.get();
}
//定义一个方法,返回一个整数数据
private static Integer getInteger(Supplier<Integer> sup){
return sup.get();
}
}
自我练习
-
定义一个类(SupplierTest),在类中提供两个方法
-
一个方法是:int getMax(Supplier< Integer > sup) 用于返回一个int数组中的最大值
-
一个方法是主方法,在主方法中调用getMax方法
-
package com.geeksss.excel.model;
import java.util.function.Supplier;
/**
* SupplierTest 使用 Supplier 接口来获取一个值
*/
public class SupplierTest {
public static void main(String[] args) {
// 初始化一个整型数组
int[] i = {3,75,32,76,98,42};
// 使用 getMax 方法来获取数组中的最大值,传递一个 Supplier 实现来计算最大值
int maxValue = getMax(()->{
int max = i[0];
// 遍历数组找到最大值
for (int j = 1; j < i.length; j++) {
if(i[j]>max){
max = i[j];
}
}
return max;
});
System.out.println(maxValue);
}
/**
* 使用 Supplier 获取一个值。
* @param sup 提供值的 Supplier 实例
* @return 由 Supplier 提供的值
*/
private static Integer getMax(Supplier<Integer> sup){
return sup.get();
}
}
实际应用场景
配置管理
Supplier可以用于配置管理,例如延迟加载配置项,确保配置在首次请求时才被读取,从而节省资源。
import java.util.function.Supplier;
public class ConfigurationManager {
private Supplier<String> configSupplier;
public ConfigurationManager(Supplier<String> configSupplier) {
this.configSupplier = configSupplier;
}
public String getConfig() {
return configSupplier.get();
}
}
// 使用示例
public class ConfigLoader {
public static void main(String[] args) {
ConfigurationManager manager = new ConfigurationManager(() -> {
// 模拟从文件或网络加载配置
return "Loaded configuration";
});
System.out.println(manager.getConfig());
}
}
4.3 Function接口
Runction<T,R>:常用的两个方法
-
R apply(T t):将此函数应用于给定的参数
-
default< V >:Function andThen(Function after):返回一个组合函数,首先将该函数应用于输入,然后将after函数应用于结果
-
Function<T,R>:接口通常用于对参数进行处理转换,然后返回一个新值(处理逻辑由Lambda表达式实现)
简单案例
import java.util.function.Function;
public class FunctionExample {
public static void main(String[] args) {
// 创建一个 Function 对象,它接受一个 String 类型的参数并返回一个 Integer 类型的结果, 引用 String::length,是 Lambda 表达式的简洁版
Function<String, Integer> stringLengthFunction = String::length;
// 使用 apply 方法调用 Function 对象,传入一个具体的 String 参数。
int length = stringLengthFunction.apply("Hello, World!");
System.out.println("The length of the string is: " + length);
}
}
自我练习
package com.dev.springBootDemo;
import java.util.function.Function;
/**
* FunctionTest 不同类型的转换函数的使用
*/
public class FunctionTest {
public static void main(String[] args) {
// 字符串转整数并打印
convert("18", s -> Integer.parseInt(s));
// 整数加法运算后转字符串并打印
convert(20, integer -> String.valueOf(integer + 18));
// 字符串转整数,整数加法运算后转字符串并打印
convert("245", s -> Integer.parseInt(s), integer -> String.valueOf(integer + 18));
}
/**
* 将字符串转换为整数并打印。
* @param s 要转换的字符串
* @param fun 字符串到整数的转换函数
*/
// 定义一个方法,把一个字符串转换成int类型,在控制台输出
private static void convert(String s, Function<String, Integer> fun) {
int i = fun.apply(s);
System.out.println(i);
}
/**
* 将整数进行运算后转换为字符串并打印。
* @param i 要转换的整数
* @param fun 整数到字符串的转换函数
*/
// 定义一个方法,把int类型数据加上一个整数之后,转换为字符串在控制台输出
private static void convert(int i, Function<Integer, String> fun) {
String s = fun.apply(i);
System.out.println(s);
}
/**
* 将字符串转换为整数,进行运算后再转换为字符串并打印。
* @param s 要转换的字符串
* @param fun1 字符串到整数的转换函数
* @param fun2 整数到字符串的转换函数
*/
// 定义一个方法,把一个字符串转换int类型,把int类型的数据加上一个整数后,转换成字符串在控制台输出
private static void convert(String s, Function<String, Integer> fun1, Function<Integer, String> fun2) {
String s1 = fun2.apply(fun1.apply(s));
System.out.println(s1);
}
}
实际应用场景
数据转换器
假设正在开发一个系统,需要处理来自不同来源的数据,这些数据可能以不同的格式存储。可以使用 Function 接口来创建转换器,将这些数据转换成统一的格式。例如,可能有一个函数将 JSON 字符串转换为对象,另一个函数将 XML 转换为对象,等等。这样,可以在系统中重用这些,提高代码的可读性和可维护性。
package com.dev.springBootDemo;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.google.gson.Gson;
import java.util.function.Function;
/**
* 数据转换器类,用于根据提供的转换函数将原始数据转换为特定类型。
*/
public class DataConverter {
/**
* 使用提供的转换函数将原始数据转换为指定类型。
*
* @param rawData 原始数据,以字符串形式表示。
* @param converter 转换函数,用于将原始数据字符串转换为目标类型T。
* @param <T> 目标数据类型。
* @return 转换后的数据对象。
*/
// 定义一个通用的转换函数,它接受一个 String 类型的原始数据和一个 Function 对象,
// 该 Function 对象负责将原始数据转换为目标类型 T。
public static <T> T convertData(String rawData, Function<String, T> converter) {
return converter.apply(rawData);
}
public static void main(String[] args) {
// 假设我们有 JSON 和 XML 数据
String jsonData = "{\"name\":\"John\", \"age\":30}";
String xmlData = "<person><name>John</name><age>30</age></person>";
// JSON 转换器
Function<String, Person> jsonConverter = s -> new Gson().fromJson(s, Person.class);
// XML 转换器
Function<String, Person> xmlConverter = s -> new XmlMapper().readValue(s, Person.class);
// 使用转换函数将JSON数据转换为Person对象
Person personFromJson = convertData(jsonData, jsonConverter);
// 使用转换函数将XML数据转换为Person对象
Person personFromXml = convertData(xmlData, xmlConverter);
System.out.println(personFromJson);
System.out.println(personFromXml);
}
}
数据映射
Function接口在数据映射和转换中扮演重要角色,例如将一种数据类型转换为另一种数据类型。
import java.util.function.Function;
public class DataMapper {
public static void main(String[] args) {
Function<String, Integer> parseInteger = Integer::parseInt;
String input = "123";
Integer output = parseInteger.apply(input);
System.out.println("Parsed integer: " + output);
}
}
4.4 Predicate接口
常用于
Predicate< T >:常用的四个方法
-
boolean test(T t):对给定的参数进行判断,返回一个布尔值(判断逻辑由Lambda表达式实现)
-
default Predicate< T > negate():返回一个逻辑的否定,对应逻辑非
-
default Predicate< T > and():返回一个组合判断,对应短路与
-
default Predicate< T > or():返回一个组合判断,对应短路或
-
isEqual():测试两个参数是否相等
-
Predicate< T >:接口通常用于判断参数是否满足指定的条件
test(T t) 、negate()
简单案例
package com.dev.springBootDemo;
import java.util.function.Predicate;
public class PredicateDemo {
public static void main(String[] args) {
// 检查字符串是否等于"张三"
boolean string = chenkString("张三", s -> s.equals("张三"));
System.out.println(string);
// 检查字符串长度是否大于8且小于18
boolean hello = chenkString("hello", s -> s.length() > 8, s -> s.length() < 18);
System.out.println(hello); // true
}
/**
* 使用单个谓词检查字符串是否满足条件。
*
* @param s 要检查的字符串
* @param pre 字符串检查谓词
* @return 如果字符串满足谓词条件,则返回true;否则返回false。
*/
// 判定给定的字符串是否满足要求
// private static boolean chenkString(String s, Predicate<String> pre){
// return pre.test(s); // true
// }
/**
* 使用单个谓词的否定检查字符串是否不满足条件。
*
* @param s 要检查的字符串
* @param pre 字符串检查谓词
* @return 如果字符串不满足谓词条件,则返回true;否则返回false。
*/
private static boolean chenkString(String s, Predicate<String> pre){
return pre.negate().test(s); // false
}
/**
* 使用两个谓词的逻辑与检查字符串是否同时满足两个条件。
*
* @param s 要检查的字符串
* @param pre 第一个字符串检查谓词
* @param pre1 第二个字符串检查谓词
* @return 如果字符串同时满足两个谓词条件,则返回true;否则返回false。
*/
// private static boolean chenkString(String s, Predicate<String> pre, Predicate<String> pre1){
// return pre.and(pre1).test(s); // false
// }java
/**
* 使用两个谓词的逻辑或检查字符串是否满足其中一个条件。
*
* @param s 要检查的字符串
* @param pre 第一个字符串检查谓词
* @param pre1 第二个字符串检查谓词
* @return 如果字符串满足两个谓词中的任何一个,则返回true;否则返回false。
*/
private static boolean chenkString(String s, Predicate<String> pre, Predicate<String> pre1){
return pre.or(pre1).test(s); // true
}
}
自我练习
-
String[] strArray = {“张三,30”, “李四,21”, “王五,18”};
-
字符串数组中由多条信息,请通过Predicate接口的拼装将符合要求的字符串筛选到集合Arraylist中,并遍历ArrayList集合
-
同时满足如下:姓名长度大于1,年龄大于20
-
分析
-
有两个判断条件,所以需要使用两个Predicate接口,对条件进行判断
-
必须同时满足两个条件,所以可以使用and方法连接两个判断条件
-
package com.dev.springBootDemo;
import java.util.ArrayList;
import java.util.function.Predicate;
/**
* 消费者测试类,使用自定义过滤函数筛选数据。
*/
public class PredicateTest {
public static void main(String[] args) {
// 初始化一个字符串数组,包含姓名和年龄信息。
String[] strArray = {
"张三,30", "李四,21", "王五,18"
};
// 使用myFilter方法筛选出姓名长度大于1且年龄大于20的人名。
ArrayList<String> arrayList = myFilter(strArray,
s -> s.split(",")[0].length() > 1,
s -> Integer.parseInt(s.split(",")[1]) > 20
);
// 遍历并打印筛选结果。
for (String array : arrayList) {
System.out.println(array);
}
}
/**
* 自定义过滤方法,根据提供的两个Predicate条件对字符串数组进行筛选。
*
* @param strArray 输入的字符串数组,每个元素包含一个姓名和一个数字。
* @param pre1 第一个过滤条件的Predicate。
* @param pre2 第二个过滤条件的Predicate。
* @return 符合所有条件的字符串集合。
*/
// 通过Predicate接口的拼装将符合要求的字符串筛选到集合Arraylist中
private static ArrayList<String> myFilter(String[] strArray, Predicate<String> pre1, Predicate<String> pre2) {
// 初始化一个ArrayList用于存储筛选结果。
ArrayList<String> array = new ArrayList<>();
// 遍历输入数组。
for (String str : strArray) {
// 如果字符串同时满足pre1和pre2两个条件,则添加到结果集合中。
if (pre1.and(pre2).test(str)) {
array.add(str);
}
}
// 返回筛选结果。
return array;
}
}
实际应用场景
权限验证
Predicate在权限验证和安全检查中非常有用,例如检查用户是否有访问特定资源的权限。
import java.util.function.Predicate;
public class PermissionChecker {
public static void main(String[] args) {
Predicate<String> hasPermission = role -> role.equals("admin");
String userRole = "admin";
boolean canAccess = hasPermission.test(userRole);
System.out.println("Can access: " + canAccess);
}
}
4.5 综合应用案例
使用这些函数式接口来处理一个员工列表,并执行诸如筛选、转换和输出等操作。
假设有一个Employee类,它有name和age属性,想要从员工列表中找出所有年龄超过30岁的员工的名字,并将这些名字转换为大写形式,最后打印出来。
-
Supplier用于初始化一个空的List<String>,这是结果容器。
-
Predicate用于筛选出年龄大于30岁的员工。
-
Function用于将员工对象转换为大写形式的名字。
-
Consumer用于将转换后的大写名字添加到结果列表中。
首先,定义Employee类:
package com.dev.springBootDemo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author zhumq
* @date 2024/7/30 23:25
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee {
private String name;
private int age;
}
接下来,使用Predicate, Function, Consumer和Supplier来解决问题:
package com.dev.springBootDemo;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
public class EmployeeProcessor {
public static void main(String[] args) {
// 创建员工列表
List<Employee> employees = new ArrayList<>();
employees.add(new Employee("张三", 35));
employees.add(new Employee("李四", 28));
employees.add(new Employee("王五", 42));
employees.add(new Employee("陈六", 31));
// 使用Supplier初始化一个空的List<String>,用于存放结果
Supplier<List<String>> supplier = ArrayList::new;
// 使用Predicate过滤年龄大于30岁的员工
Predicate<Employee> predicate = employee -> employee.getAge() > 30;
// 使用Function将Employee转换为其大写名字
Function<Employee, String> function = employee -> employee.getName().toUpperCase();
// 使用Consumer将转换后的名字添加到List中
Consumer<String> consumer = supplier.get()::add;
// 执行操作
List<String> filteredNames = employees.stream()
.filter(predicate)
.map(function)
.collect(Collectors.toList());
// 使用Consumer打印结果
filteredNames.forEach(System.out::println);
}
}
张三 王五 陈六
五、Lambda 应用
1.Consumer (消费型接口)
Consumer用于消费一个对象,常用于Stream的forEach()方法。
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
public class ConsumerExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// 使用Consumer打印每个名字
names.forEach(System.out::println);
}
}
2.Supplier (供给型接口)
Supplier用于生成一个对象,常用于初始化数据源或延迟加载。
import java.util.function.Supplier;
public class SupplierExample {
public static void main(String[] args) {
Supplier<String> helloWorld = () -> "Hello, World!";
// 使用Supplier获取结果
System.out.println(helloWorld.get());
}
}
3..Function (函数型接口)
Function用于将一个类型的数据转换为另一个类型的数据,常用于Stream的map()方法。
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
public class FunctionExample {
public static void main(String[] args) {
List<String> words = Arrays.asList("one", "two", "three");
// 使用Function将字符串转换为大写
List<String> upperCaseWords = words.stream().map(String::toUpperCase).toList();
System.out.println("Upper case words: " + upperCaseWords);
}
}
4..Predicate (断言型接口)
Predicate用于判断一个对象是否满足某个条件,常用于Stream的filter()方法。
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
public class PredicateExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
// 使用Predicate过滤出偶数
List<Integer> evenNumbers = numbers.stream().filter(n -> n % 2 == 0).toList();
System.out.println("Even numbers: " + evenNumbers);
}
}