"if optional is empty, call next method returning optional, if not return this non-empty optional" 如何以函数式的方式写多次?

How to write "if optional is empty, call next method returning optional, if not return this non-empty optional" several times in a functional style?

假设我有这个方法

public Optional<String> validateAndReturnErrorMessage(SomeEcommerceSale s) {
    Optional<String> errorWithItem = validateItem(s.getItem());
    if (errorWithItem.isPresent()) return errorWithItem;

    Optional<String> errorWithPayment = validatePayment(s.getPayment());
    if (errorWithPayment.isPresent()) return errorWithPayment;
    
    // assume I have several other cases like the 2 above

    return Optional.empty(); // meaning there were no errors

我的问题是,由于 return <T> 而不是 Optional<T>,是否有一种本地方法可以将其重写为更实用的方式而无需多个松耦合 return 语句?

编辑

我想一一检查验证,因为它们是外部的而且很重。这样,我只会调用必要的

只需使用or:

If a value is present, returns an Optional describing the value, otherwise returns an Optional produced by the supplying function.

return validatePayment(s.getItem()).or(() -> validatePayment(s.getPayment()));

这种情况就是Optional.or添加的。它是在 Java 9 中添加的,因此如果您仍在使用 Java 8,则无法使用它。

return validateItem(s.getItem())
    .or(() -> validatePayment(req.getPayment()))
    .or(() -> /*another one*/);

如果你卡在Java 8,你可以写一个辅助方法

public static <T> Optional<T> firstNonEmpty(List<Supplier<Optional<T>>> supplierList) {
    for (Supplier<Optional<T>> supplier : supplierList) {
        Optional<T> value = supplier.get();
        if (value.isPresent()) return value;
    }
    return Optional.empty();
}

它像这样使用它:

return firstNonEmpty(
    Arrays.asList(
        () -> validateItem(s.getItem()),
        () -> validatePayment(req.getPayment()),
        () -> /*another one*/
    )
);

如果您有 long/dynamic 个要验证的项目列表,您可能需要使用流:

return Stream.<Supplier<String>>of(s::getItem, req::getPayment, ...)
         .map(s -> this.validateItem(s.get()))
         .filter(Predicate.not(Optional::isEmpty)) //or filter(o -> !o.isEmpty())
         .findFirst();