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

复制流以避免“流已被操作或关闭”

赵高韵
2023-03-14

我想复制一个Java 8流,这样我可以处理它两次。我可以收集作为列表并从中获取新流;

// doSomething() returns a stream
List<A> thing = doSomething().collect(toList());
thing.stream()... // do stuff
thing.stream()... // do other stuff

但我觉得应该有一个更高效/更优雅的方法。

有没有一种方法可以复制流而不将其变成集合?

我实际上正在处理一个或者流,所以在移动到右侧投影并以另一种方式处理之前,希望先以一种方式处理左侧投影。类似于这样(到目前为止,我不得不使用tolist技巧)。

List<Either<Pair<A, Throwable>, A>> results = doSomething().collect(toList());

Stream<Pair<A, Throwable>> failures = results.stream().flatMap(either -> either.left());
failures.forEach(failure -> ... );

Stream<A> successes = results.stream().flatMap(either -> either.right());
successes.forEach(success -> ... );

共有1个答案

楚宏胜
2023-03-14

我认为你对效率的假设有点倒退。如果只使用一次数据,就会获得巨大的效率回报,因为您不必存储数据,并且流提供了强大的“循环融合”优化,可以使整个数据高效地通过管道流动。

如果您想重用相同的数据,那么根据定义,您要么必须生成它两次(确定性地),要么存储它。如果它已经碰巧在一个集合中,那很好;那么迭代两次是很便宜的。

我们用“分叉溪流”做了设计实验。我们发现,支持这一计划是有实际成本的;它以牺牲不常见的情况为代价,加重了普通情况(使用一次)的负担。最大的问题是处理“当两个管道不以相同的速率消耗数据时会发生什么”。现在你又回到缓冲了。这是一个明显不起作用的特点。

如果您希望重复操作相同的数据,可以存储它,或者将您的操作结构化为使用者,并执行以下操作:

stream()...stuff....forEach(e -> { consumerA(e); consumerB(e); });

您还可以研究一下RxJava库,因为它的处理模型更适合这种“流分叉”。

 类似资料:
  • 我想复制一个Java8流,这样我可以处理它两次。我可以

  • 问题内容: 我想复制一个Java 8流,以便可以处理两次。我可以collect列出并从中获得新的信息流; 但我认为应该有一种更有效/更优雅的方法。 有没有一种方法可以复制流而不将其转换为集合? 我实际上正在使用 流,因此想先处理左侧投影,然后再移至右侧投影并以另一种方式处理。有点像这样(到目前为止,我被迫使用这种技巧)。 问题答案: 你可以将局部变量与一起使用,以设置流管道的公共部分。 从http

  • 方法是 现在我试着像这样改成stream,但我不知道这种改是否正确: 如何避免出现例外,解决问题? 我应该以某种方式重构代码吗?

  • 下面是我的代码: 从下面的函数调用上面的函数: 我不知道为什么。

  • 问题内容: 我正在尝试使用Stream API生成Order实例。我有一个创建订单的工厂函数,并且使用DoubleStream初始化订单金额。 如果我使用文字(1.0)初始化Order实例,则可以正常工作。当我使用doubleStream创建随机数量时,将引发异常。 问题答案: 答案在(重点是我的)的javadoc中: 流仅应操作一次(调用中间流或终端流操作) 。例如,这排除了“分叉”流,其中相同