163. Java Lambda 表达式 - Function 的链式组合
在函数式编程中,我们常常希望把多个功能组合起来形成一个新的功能。Java 的 Function<T, R>
接口为此提供了两个非常实用的默认方法:
🧩 andThen()
------ 先执行当前函数,再执行参数函数
java
Function<T, R> f1;
Function<R, V> f2;
Function<T, V> result = f1.andThen(f2);
🧩 compose()
------ 先执行参数函数,再执行当前函数
java
Function<T, R> f1;
Function<U, T> f2;
Function<U, R> result = f1.compose(f2);
🎯 理解两者的执行顺序
方法名 | 执行顺序 | 相当于代码 |
---|---|---|
andThen() |
先 f1 后 f2 |
f2(f1(x)) |
compose() |
先 f2 后 f1 |
f1(f2(x)) |
它们实现的是相同的功能组合 ,只是调用方式不同,谁写在前面,谁先执行。
📦 实例演示:名字处理链
假设我们有一组名字,需要做如下处理:
- 去掉前后空格;
- 全部转为大写;
- 添加前缀 "
Hello,
"。
我们可以把这几个步骤封装成函数:
java
Function<String, String> trim = String::trim;
Function<String, String> toUpper = String::toUpperCase;
Function<String, String> addPrefix = name -> "Hello, " + name;
✅ 方式一:使用 andThen()
链接函数
java
Function<String, String> greet = trim.andThen(toUpper).andThen(addPrefix);
System.out.println(greet.apply(" alice ")); // 输出:Hello, ALICE
执行顺序是:
trim(" alice ")
→"alice"
toUpper("alice")
→"ALICE"
addPrefix("ALICE")
→"Hello, ALICE"
✅ 方式二:使用 compose()
组合函数(写法反过来)
java
Function<String, String> greet = addPrefix.compose(toUpper).compose(trim);
System.out.println(greet.apply(" alice ")); // 输出:Hello, ALICE
⚠️ 虽然顺序看起来反了,其实执行顺序和 andThen()
完全一样!
🧠 小贴士:如何选用?
情况 | 推荐方法 |
---|---|
自然顺序思维(从左到右) | andThen() |
倒推逻辑(从右到左) | compose() |
🛑 类型兼容性注意
不论你是使用 andThen()
还是 compose()
,都要确保类型兼容:
f1.andThen(f2)
:f1
的返回类型必须是f2
的输入类型。f1.compose(f2)
:f2
的返回类型必须是f1
的输入类型。
java
Function<Integer, Double> half = i -> i / 2.0;
Function<Double, String> asString = d -> "Result: " + d;
// 合法组合
Function<Integer, String> composed = half.andThen(asString);
🧪 练习题(课堂互动)
编写一个函数组合链,接收一个字符串,输出结果如下格式:
"Length: <长度>"
提示步骤:
- 去掉空格;
- 获取长度;
- 拼接前缀字符串。