当前位置: 首页 > 知识库问答 >
问题:

flatMap保证会偷懒吗?[副本]

终波涛
2023-03-14
urls.stream()
    .flatMap(url -> fetchDataFromInternet(url).stream())
    .filter(...)
    .findFirst()
    .get();
    Stream.of("one", "two", "three")
            .flatMap(num -> {
                System.out.println("Processing " + num);
                // return FetchFromInternetForNum(num).data().stream();
                return Stream.of(num);
            })
            .peek(num -> System.out.println("Peek before filter: "+ num))
            .filter(num -> num.length() > 0)
            .peek(num -> System.out.println("Peek after filter: "+ num))
            .forEach(num -> {
                System.out.println("Done " + num);
            });

输出:

Processing one
Peek before filter: one
Peek after filter: one
Done one
Processing two
Peek before filter: two
Peek after filter: two
Done two
Processing three
Peek before filter: three
Peek after filter: three
Done three

如果要执行此行为,API应该让函数返回iterable而不是流。

换句话说:链接

共有1个答案

赵健柏
2023-03-14

在当前的实现下,flatmap是急切的;与任何其他有状态的中间操作(如sorteddistinct)一样。而且很容易证明:

 int result = Stream.of(1)
            .flatMap(x -> Stream.generate(() -> ThreadLocalRandom.current().nextInt()))
            .findFirst()
            .get();

    System.out.println(result);

flatmap被急切地计算时,这永远不会结束。对于您的示例:

urls.stream()
    .flatMap(url -> fetchDataFromInternet(url).stream())
    .filter(...)
    .findFirst()
    .get();

这意味着对于每个URLFlatMap将阻止后面的所有其他操作,即使您只关心一个操作。因此,假设从单个url中,您的FetchDataFromInternet(url)生成10_000行,那么您的FindFirst将不得不等待计算出所有10_000,即使您只关心其中一个。

编辑

这在Java10中得到了修正,在这里我们又找回了懒惰:参见JDK-8075939

编辑2

 类似资料:
  • 问题内容: 考虑以下代码: 当第一个URL够用时会被要求输入第二个URL吗? 我尝试了一个较小的示例,它看起来像预期的那样工作。即一个一个地处理数据,但是可以依靠这种行为吗?如果没有,在帮助之前打电话吗? 输出: 更新 :如果对实施很重要,请使用官方Oracle JDK8 答案 :根据下面的评论和答案,flatmap部分是惰性的。即完全读取第一个流,并且仅在需要时才读取下一个。渴望读取一个流,但是

  • 使用JPA EntityManager和JPA查询对象,我如何覆盖在查询中惰性获取注释@OneToMany(fetch=FetchType.EAGER)的内容? 如果我有hibernate查询对象,我可以让它创建一个criteria对象,并使用它将fetch类型设置为lazy。但我必须使用JPA查询对象。这个问题有什么解决办法吗?

  • 我被要求检索树节点的每个叶节点。我很快想到我可以在一行中完成这项工作! 第一眼看上去很不错,但很快它就遇到了一个,如果树深度达到~10,这是我无法接受的。后来我开发了一个没有递归和流的实现(但我的大脑被烤坏了),但我仍然想知道是否有一种方法可以用流做递归,因为我发现不接触流内部是不可能做到的。它需要一个新的Op,比如来做到这一点,否则我必须每一步都将所有结果收集到中,然后再对该进行操作: 不像看起

  • 问题内容: 抱歉,如果这没有任何意义,我是Python的新手! 从一个解释测试中,我可以看到,并且都产生一个空列表: 根据到目前为止的经验,创建对象的唯一方法是调用其构造函数(),但是仅键入时我看不到这种情况。因此,通过执行,Python是否会将其映射到对的调用? 问题答案: 不,Python不会调用,或者您可以通过分配给list来影响创建的类型,但您不能这样做: 是用于创建列表的语法。它是一种内

  • Mongock看起来很有希望。我们希望在具有多个并行运行的副本的kubernetes服务中使用它。 我们希望在部署我们的服务时,第一个副本将获得mongockLock,并且它的所有ChangeLogs/ChangeSets将在其他副本尝试运行它们之前完成。 我们在kubernetes环境中运行一个mongodb实例,我们希望mongock变更日志/变更集只执行一次。 mongockLock是否保证