Better way to create a stream of functions?

时间:2017-12-17 08:29:31

标签: java java-8 java-stream functional-interface

I wish to do lazy evaluation on a list of functions I've defined as follows;

Optional<Output> output = Stream.<Function<Input, Optional<Output>>> of(
                    classA::eval, classB::eval, classC::eval)
            .map(f -> f.apply(input))
            .filter(Optional::isPresent)
            .map(Optional::get)
            .findFirst();

where as you see, each class (a, b & c) has an Optional<Output> eval(Input in) method defined. If I try to do

Stream.of(...)....

ignoring explicit type, it gives

T is not a functional interface

compilation error. Not accepting functional interface type for T generic type in .of(T... values)


Is there a snappier way of creating a stream of these functions? I hate to explicitly define of method with Function and its in-out types. Wouldn't it work in a more generic manner?

This issue stems from the topic of the following question;
Lambda Expression and generic method

2 个答案:

答案 0 :(得分:4)

你可以把它分成两行:

Stream<Function<Input, Optional<Output>>> stream = Stream
          .of(classA::eval, classB::eval, classC::eval);
Optional<Output> out = stream.map(f -> f.apply(input))
          .filter(Optional::isPresent)
          .map(Optional::get)
          .findFirst();

或使用演员:

Optional<Output> out = Stream.of(
                (<Function<Input, Optional<Output>>>)classA::eval, 
                classB::eval, 
                classC::eval)
        .map(f -> f.apply(input))
        .filter(Optional::isPresent)
        .map(Optional::get)
        .findFirst();

但我不认为您可以避免在某处指定Stream元素的类型 - Function<Input, Optional<Output>>,否则编译器无法从方法引用中推断它。

答案 1 :(得分:3)

有一种方法可以省略Function<Input, Optional<Output>>类型,但它不一定是改进

Optional<Output> o =
        Stream.concat(Stream.of(input).map(classA::eval),
                Stream.concat(Stream.of(input).map(classB::eval),
                              Stream.of(input).map(classC::eval)))
                .filter(Optional::isPresent)
                .map(Optional::get)
                .findFirst();

并且它不会缩放。

看来,最好的选择是等待Java-9,你可以使用

Optional<Output> o = classA.eval(input)
           .or(() -> classB.eval(input))
           .or(() -> classC.eval(input));