【问题标题】:Stream till value found - optional [duplicate]流式传输直到找到值 - 可选[重复]
【发布时间】:2019-02-12 14:24:55
【问题描述】:

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

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();
    }

我检查了以下文档:

  1. 存在

如果存在值则返回 {@code true},否则返回 {@code 错误}。

  1. findFirst()

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

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

first
second
someValue

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

【问题讨论】:

    标签: java java-stream optional


    【解决方案1】:

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

    Stream#findFirst 是短路终端操作。但是,当您调用 Stream.of(first(), second()) 时会调用这些方法。这可以用以下 sn-p 证明:

    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());
    

    输出:

    first
    second
    Hello World!
    someValue
    

    为了防止first()second() 在调用Stream#of 时执行,一种解决方案是将它们包装在Supplier&lt;Optional&lt;String&gt;&gt; 中:

    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());
    

    输出:

    first
    someValue
    

    【讨论】:

    • Stream&lt;Supplier&lt;Optional&lt;String&gt;&gt;&gt; supplierStream = Stream.of(Test::first, Test::second); Optional&lt;String&gt; s = supplierStream... 可以帮助提高可读性。
    • 好点,我也不是演员的忠实粉丝。我会改变它:)
    • 您也可以使用.findFirst() .orElse(Optional.empty()).map(Optional::get) .findFirst() 来代替.findFirst() .flatMap(Function.identity())。貌似是recurring question,但是通过Stackoverflow的搜索功能确实很难找到……
    【解决方案2】:

    问题不在于findFirst 没有短路,而是Stream.of(first(), second()) 导致first()second 立即(而不是延迟)执行。它本质上被评估为任何普通表达式。

    换句话说,即使你的主要方法只是

    final public static void main(String[] args) throws Exception {
        Stream.of(first(), second());
    }
    

    它仍然会立即执行first()second()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-24
      • 2021-05-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-11
      • 2016-05-03
      相关资源
      最近更新 更多