直到找到值 - 可选

Bar*_*tek 4 java optional java-stream

我想在找到第一个值时终止流的执行.但是,当我在下面运行代码时,它会显示即使第一个方法存在值,也会调用两个方法.

public static void main(String[] args) {

        Optional<String> s = Stream.of(first(), second())
                .filter(Optional::isPresent)
                .findFirst()
                .flatMap(Function.identity());

        System.out.println(s.get());
    }

    private static Optional<String> first() {
        System.out.println("first");
        return Optional.of("someValue");
    }

    private static Optional<String> second() {
        System.out.println("second");
        return Optional.empty();
    }
Run Code Online (Sandbox Code Playgroud)

我在文档中检查了:

  1. 存在

如果存在值,则返回{@code true},否则返回{@code false}.

  1. 使用FindFirst()

返回描述此流的第一个元素的{@link Optional},如果流为空,则返回空的{@code Optional}.如果流没有遭遇顺序,则可以返回任何元素.

所以它遇到的第一个条件,第二个条件似乎也满足,因为它返回:

first
second
someValue
Run Code Online (Sandbox Code Playgroud)

如果第一个值存在,如何退出执行,而不执行第二个方法?

Jac*_* G. 6

如果第一个值存在,如何退出执行,而不执行第二个方法?

Stream#findFirst是一种短路终端操作.但是,调用时会调用这些方法Stream.of(first(), second()).这可以通过以下代码段证明:

Optional<String> s = Stream.of(first(), second())
                           .peek($ -> System.out.println("Hello World!"))
                           .filter(Optional::isPresent)
                           .findFirst()
                           .flatMap(Function.identity());

System.out.println(s.get());
Run Code Online (Sandbox Code Playgroud)

输出:

first
second
Hello World!
someValue
Run Code Online (Sandbox Code Playgroud)

为了防止first()second()在执行调用时执行Stream#of,一个解决方案是将它们包装在Supplier<Optional<String>>:

Stream<Supplier<Optional<String>>> stream = Stream.of(Test::first, Test::second);

Optional<String> s = stream.map(Supplier::get)
                           .filter(Optional::isPresent)
                           .findFirst()
                           .flatMap(Function.identity());

System.out.println(s.get());
Run Code Online (Sandbox Code Playgroud)

输出:

first
someValue
Run Code Online (Sandbox Code Playgroud)