Java8中如何组合两个Function实现订单可配送判断
你遇到的问题核心是**Function的andThen方法并不适合用来组合两个判断条件**——它的设计逻辑是把前一个函数的输出作为后一个函数的输入,但你这里两个Function<Order, Boolean>的输入都是Order、输出都是Boolean,类型完全不匹配,所以才会抛出编译错误。
下面给你几种实用的解决方案:
方案一:改用Predicate(推荐)
Predicate就是专门为布尔判断场景设计的接口,它自带and()方法可以直接组合多个判断条件,完美契合你的需求:
import java.util.function.Predicate; public class OrderFunctions { public Predicate<Order> isReadyToDeliver() { Predicate<Order> orderStateReady = o -> o.getState() == OrderState.READY_TO_SEND; Predicate<Order> allProductsAvailable = o -> o.getProducts() .stream() .allMatch(product -> product.getState() == ProductState.AVAILABLE); return orderStateReady.and(allProductsAvailable); } }
如果之后需要把Predicate转换成Function,只需要用方法引用即可:
Function<Order, Boolean> function = orderStateReady.and(allProductsAvailable)::test;
方案二:手动组合两个Function的逻辑
如果一定要保留Function的返回类型,直接在返回时同时调用两个函数的apply方法,用逻辑与(&&)组合结果就好,简单直接:
public class OrderFunctions { public Function<Order, Boolean> isReadyToDeliver() { Function<Order, Boolean> orderState = o -> o.getState() == OrderState.READY_TO_SEND; Function<Order, Boolean> productState = o -> o.getProducts() .stream() .allMatch(product -> product.getState() == ProductState.AVAILABLE); return order -> orderState.apply(order) && productState.apply(order); } }
方案三:自定义Function组合工具(进阶复用)
如果你需要多次组合类似的Function<T, Boolean>,可以写一个通用的工具方法来实现逻辑与的组合:
import java.util.function.Function; public class OrderFunctions { public Function<Order, Boolean> isReadyToDeliver() { Function<Order, Boolean> orderState = o -> o.getState() == OrderState.READY_TO_SEND; Function<Order, Boolean> productState = o -> o.getProducts() .stream() .allMatch(product -> product.getState() == ProductState.AVAILABLE); return combineAnd(orderState, productState); } private <T> Function<T, Boolean> combineAnd(Function<T, Boolean> func1, Function<T, Boolean> func2) { return t -> func1.apply(t) && func2.apply(t); } }
这个工具方法可以复用在任何需要组合布尔值输出Function的场景里。
再聊聊为什么andThen不行
最后帮你理清楚错误根源:Function的andThen方法签名是default <V> Function<T,V> andThen(Function<? super R,? extends V> after),其中T是输入类型,R是前一个函数的输出类型。对于你的orderState(Function<Order, Boolean>),调用andThen时,传入的参数必须是**输入为Boolean**的函数,但你的productState输入是Order,类型完全不匹配,编译器自然会报错啦。
内容的提问来源于stack exchange,提问作者Javad Akbari

