首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Stream<Stream>:flatMap与减缩

Stream<Stream>:flatMap与减缩
EN

Stack Overflow用户
提问于 2016-06-22 18:19:18
回答 1查看 4K关注 0票数 10

如果我执行以下“连接”两个流的代码

  • 首先由flatMapping a Stream<Stream<Integer>>
  • 然后,通过使用Stream<Stream<Integer>>减少Stream.concat()

在这两种情况下,我都得到了相同的正确结果,但是过滤操作的次数是不同的。

代码语言:javascript
运行
复制
public class FlatMapVsReduce {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);

        Predicate<Integer> predicate1 = i -> {
            System.out.println("testing first condition with " + i);
            return i == 3;
        };

        Predicate<Integer> predicate2 = i -> {
            System.out.println("testing second condition with " + i);
            return i == 7;
        };

        System.out.println("Testing with flatMap");
        Integer result1 =
            Stream.of(list.stream().filter(predicate1),
                      list.stream().filter(predicate2))
                  .flatMap(Function.identity())
                  .peek(i -> System.out.println("peeking " + i))
                  .findFirst()
                  .orElse(null);
        System.out.println("result1 = " + result1);

        System.out.println();
        System.out.println("Testing with reduce");
        Integer result2 =
            Stream.of(list.stream().filter(predicate1),
                      list.stream().filter(predicate2))
                  .reduce(Stream::concat)
                  .orElseGet(Stream::empty)
                  .peek(i -> System.out.println("peeking " + i))
                  .findFirst()
                  .orElse(null);
        System.out.println("result2 = " + result2);
    }
}

我在这两种情况下都得到了预期的结果。但是,第一个操作对集合的每个元素应用第一个筛选器,而第二个操作在满足一个元素后立即停止。产出如下:

代码语言:javascript
运行
复制
Testing with flatMap
testing first condition with 1
testing first condition with 2
testing first condition with 3
peeking 3
testing first condition with 4
testing first condition with 5
testing first condition with 6
testing first condition with 7
testing first condition with 8
testing first condition with 9
result1 = 3

Testing with reduce
testing first condition with 1
testing first condition with 2
testing first condition with 3
peeking 3
result2 = 3

为什么两人的行为有区别?在第一个场景中,JDK代码能比第二个场景更高效吗?或者flatMap中有什么东西使得它不可能实现呢?

增编:以下备选方案与使用减缩的方法一样有效,但我仍然无法解释为什么:

代码语言:javascript
运行
复制
    Integer result3 = Stream.of(predicate1, predicate2)
                            .flatMap(c -> list.stream().filter(c).limit(1))
                            .peek(i -> System.out.println("peeking " + i))
                            .findFirst()
                            .orElse(null);
    System.out.println("result3 = " + result3);
EN

回答 1

Stack Overflow用户

发布于 2016-06-22 18:43:58

flatMap in openJDK的实现来看,我理解的是flatMap将传入流的全部内容推入下游:

代码语言:javascript
运行
复制
result.sequential().forEach(downstreamAsInt);

另一方面,Stream::concat似乎在处理拉链,而不是立即发送所有内容。

我怀疑你的测试没有显示出全貌:

  • flatMap中,只有当第一个流耗尽时才考虑第二个流。
  • reduce中,所有流都被推到最后的级联流中,因为在消耗输入流的所有内容之前,简化的对象是没有意义的。

这意味着使用一个或另一个取决于您的输入有多复杂。如果您有一个无限的Stream<Stream<Integer>>,减少将永远不会完成。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37975549

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档