函数组合(Functional composition)是指将多个函数连接在一起,使得一个函数的输出作为下一个函数的输入。这种编程技术在函数式编程中非常常见。
Java 8 引入了对函数式编程的支持,包括 Function 接口和用于函数组合的方法。本文将介绍如何在 Java 中使用函数组合。
Function 接口
Java 的 java.util.function.Function 接口表示一个接受一个参数并返回一个结果的函数。该接口定义如下(简化版):
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
除了 apply() 方法外,Function 接口还提供了两个用于函数组合的默认方法:
andThen(Function<? super R, ? extends V> after)
返回一个先执行当前函数、再执行after函数的组合函数。compose(Function<? super V, ? extends T> before)
返回一个先执行before函数、再执行当前函数的组合函数。
使用 andThen 进行函数组合
andThen() 方法允许你将一个函数的结果传递给另一个函数。例如:
Function<Integer, Integer> multiplyBy2 = x -> x * 2;
Function<Integer, String> toString = x -> x.toString();
Function<Integer, String> multiplyBy2AndToString = multiplyBy2.andThen(toString);
String result = multiplyBy2AndToString.apply(5); // 结果为 "10"
在这个例子中,首先将输入值乘以 2,然后将结果转换为字符串。
使用 compose 进行函数组合
compose() 方法与 andThen() 相反:它先应用传入的函数,再应用当前函数。例如:
Function<String, Integer> parseInt = Integer::parseInt;
Function<Integer, Integer> add10 = x -> x + 10;
Function<String, Integer> parseIntAndAdd10 = add10.compose(parseInt);
Integer result = parseIntAndAdd10.apply("5"); // 结果为 15
这里,首先将字符串 "5" 解析为整数 5,然后加上 10 得到 15。
andThen 与 compose 的区别
简单来说:
f.andThen(g)等价于g(f(x))f.compose(g)等价于f(g(x))
因此,顺序是关键。
实际应用场景
函数组合特别适用于数据处理管道(pipeline)。例如,你可能需要对用户输入进行清洗、验证、转换和格式化。每个步骤都可以表示为一个函数,然后通过 andThen() 或 compose() 将它们组合起来。
示例:处理电子邮件地址
Function<String, String> trim = String::trim;
Function<String, String> toLowerCase = String::toLowerCase;
Function<String, String> validate = email -> {
if (email.contains("@")) return email;
else throw new IllegalArgumentException("Invalid email");
};
Function<String, String> processEmail = trim
.andThen(toLowerCase)
.andThen(validate);
String result = processEmail.apply(" USER@EXAMPLE.COM "); // "user@example.com"
总结
- 函数组合是将多个函数链接成一个处理链的技术。
- Java 的
Function接口提供了andThen()和compose()方法来实现组合。 andThen()先执行当前函数,再执行后续函数;compose()则相反。- 函数组合有助于构建清晰、可复用和可测试的数据处理逻辑。