🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 函数组合 函数组合(Function Composition)意为“多个函数组合成新函数”。它通常是函数式编程的基本组成部分。在前面的 `TransformFunction.java` 类中,有一个使用 `andThen()` 的函数组合示例。一些 `java.util.function` 接口中包含支持函数组合的方法 [^7]。 | 组合方法 | 支持接口 | | :----- | :----- | | `andThen(argument)` <br> 根据参数执行原始操作 | **Function <br> BiFunction <br> Consumer <br> BiConsumer <br> IntConsumer <br> LongConsumer <br> DoubleConsumer <br> UnaryOperator <br> IntUnaryOperator <br> LongUnaryOperator <br> DoubleUnaryOperator <br> BinaryOperator** | | `compose(argument)` <br> 根据参数执行原始操作 | **Function <br> UnaryOperator <br> IntUnaryOperator <br> LongUnaryOperator <br> DoubleUnaryOperator** | | `and(argument)` <br> 短路**逻辑与**原始谓词和参数谓词 | **Predicate <br> BiPredicate <br> IntPredicate <br> LongPredicate <br> DoublePredicate** | | `or(argument)` <br> 短路**逻辑或**原始谓词和参数谓词 | **Predicate <br> BiPredicate <br> IntPredicate <br> LongPredicate <br> DoublePredicate** | | `negate()` <br> 该谓词的**逻辑否**谓词| **Predicate <br> BiPredicate <br> IntPredicate <br> LongPredicate <br> DoublePredicate** | 下例使用了 `Function` 里的 `compose()`和 `andThen()`。代码示例: ```java // functional/FunctionComposition.java import java.util.function.*; public class FunctionComposition { static Function<String, String> f1 = s -> { System.out.println(s); return s.replace('A', '_'); }, f2 = s -> s.substring(3), f3 = s -> s.toLowerCase(), f4 = f1.compose(f2).andThen(f3); public static void main(String[] args) { System.out.println( f4.apply("GO AFTER ALL AMBULANCES")); } } ``` 输出结果: ``` AFTER ALL AMBULANCES _fter _ll _mbul_nces ``` 这里我们重点看正在创建的新函数 `f4`。它调用 `apply()` 的方式与常规几乎无异[^8]。 当 `f1` 获得字符串时,它已经被`f2` 剥离了前三个字符。这是因为 `compose(f2)` 表示 `f2` 的调用发生在 `f1` 之前。 下例是 `Predicate` 的逻辑运算演示.代码示例: ```java // functional/PredicateComposition.java import java.util.function.*; import java.util.stream.*; public class PredicateComposition { static Predicate<String> p1 = s -> s.contains("bar"), p2 = s -> s.length() < 5, p3 = s -> s.contains("foo"), p4 = p1.negate().and(p2).or(p3); public static void main(String[] args) { Stream.of("bar", "foobar", "foobaz", "fongopuckey") .filter(p4) .forEach(System.out::println); } } ``` 输出结果: ``` foobar foobaz ``` `p4` 获取到了所有谓词并组合成一个更复杂的谓词。解读:如果字符串中不包含 `bar` 且长度小于 5,或者它包含 `foo` ,则结果为 `true`。 正因它产生如此清晰的语法,我在主方法中采用了一些小技巧,并借用了下一章的内容。首先,我创建了一个字符串对象的流,然后将每个对象传递给 `filter()` 操作。 `filter()` 使用 `p4` 的谓词来确定对象的去留。最后我们使用 `forEach()` 将 `println` 方法引用应用在每个留存的对象上。 从输出结果我们可以看到 `p4` 的工作流程:任何带有 `"foo"` 的字符串都得以保留,即使它的长度大于 5。 `"fongopuckey"` 因长度超出且不包含 `foo` 而被丢弃。