函数组合(Functional Composition)

更新于 2025-12-29

函数组合(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() 则相反。
  • 函数组合有助于构建清晰、可复用和可测试的数据处理逻辑。