多个可选实例的逻辑OR?

时间:2014-11-22 06:15:54

标签: java java-stream optional

使用Java核心API表示以下算法是否有更优雅的方法?

Optional<Float> input = Optional.of(A);
Optional<Float> output = input.map(function1).map(function2);
if (!output.isPresent())
{
  output = input.map(function1).map(function2);
  if (!output.isPresent())
  {
    output = input.map(function3).map(function4);
      if (!output.isPresent())
        output = input.map(function5).map(function6);
  }
}

也就是说,不是嵌套isPresent()的多个调用,而是要调用map()之类的方法,但只有在没有值的情况下才会调用它。

在一个理想的世界里,我想调用以下内容:

Optional<Float> output = input.or(input.map(function1).map(function2), input.map(function2).map(function3), input.map(function4).map(function5));

这是我迄今为止所做的,但我们可以做得更好吗?

public class Optionals
{
    /**
     * @param <T>       the type of value returned by the Optionals
     * @param suppliers one or more suppliers that return a supplier
     * @return the first Optional that {@link Optional#isPresent() isPresent()}
     */
    public static <T> Optional<T> or(Supplier<Optional<T>>... suppliers)
    {
        for (Supplier<Optional<T>> supplier: suppliers)
        {
            Optional<T> candidate = supplier.get();
            if (candidate.isPresent())
                return candidate;
        }
        return Optional.empty();
    }

    /**
     * Prevent construction.
     */
    private Optionals()
    {
    }
}

4 个答案:

答案 0 :(得分:2)

Optional有一个orElse方法;如果你调用它,它将返回Optional中的值(如果它不为空),或者传递给orElse的值(如果它为空)。

所以你可以使用嵌套的orElse调用,如下所示:

Float output = input.map(function1).map(function2)
    .orElse(input.map(function3).map(function4)
        .orElse(input.map(function5).map(function6)
            .orElse(0.0f)));

请注意,最终结果不是Optional<Float>而是Float。如果您没有想要一个默认返回值,例如0.0f,当没有映射返回值时,您可以例如让它抛出异常:

Float output = input.map(function1).map(function2)
    .orElse(input.map(function3).map(function4)
        .orElse(input.map(function5).map(function6)
            .orElseThrow(() -> new IllegalStateException("No result"))));

答案 1 :(得分:1)

return Arrays.stream(suppliers).filter(supplier -> supplier.get().isPresent()).toArray();

答案 2 :(得分:0)

在这种情况下,我不喜欢Supplier计划,可能更喜欢这种方法:

public static void main(String[] args) {

    Float x = 1.0f;
    final Optional<Float> input = Optional.of(x);
    Optional<Float> output = firstPresent(input, (a) -> a.map(FUNCTION1).map(FUNCTION2),
                                     (a) -> a.map(FUNCTION3).map(FUNCTION4),
                                     (a) -> a.map(FUNCTION5).map(FUNCTION6));
}

@SafeVarargs
public static <I,O> Optional<O> firstPresent(Optional<I> input, Function<Optional<I>, Optional<O>>... functions) {
    for (Function<Optional<I>, Optional<O>> function : functions) {
        final Optional<O> output = function.apply(input);
        if(output.isPresent()) {
            return output;
        }
    }
    return Optional.empty();
}

答案 3 :(得分:0)

通过Java8谓词实现'多条件'逻辑AND的方法(作者Yosi Lev):

public static void main(String[] args) {
 Optional<String> stringOptional = Optional.of( "this is a string" );
 Predicate<String> isNotNull  = s-> s != null;
 Predicate<String> isSizeGT0  = s-> s.length() > 0 ;
 Predicate<String> isSizeGT20 = s-> s.length() > 20 ;
 // calling isOk() with all required Predicates to be approved:
 System.out.println(isOk(stringOptional, isNotNull, isSizeGT0, isSizeGT20));
}//main()

@SafeVarargs
private static <I> boolean isOk(Optional<I> inp, Predicate<I>... predicates){
 // Enforce all predicates on input..
 boolean b = Arrays.stream( predicates ).allMatch( pr->pr.test( inp.get()));
 return b; 
}