Java 如何从一个流对象执行多个(重用)缩减/映射/混合操作

Java 如何从一个流对象执行多个(重用)缩减/映射/混合操作,java,performance,java-stream,Java,Performance,Java Stream,我知道Java流对象不允许分叉流。但也可以合理地想象一个人会对同一个流执行多个操作。假设我想映射一个对象列表,但也要汇总所有对象的测量值。我想知道是否可以在不将数据转储到列表中的情况下执行此操作 Stream<Thing> thingStream = ...; int accumulation = thingStream.mapToInt(Thing::measure).sum(); List<Another> results = thingStream.map(t -&

我知道Java流对象不允许
分叉流
。但也可以合理地想象一个人会对同一个流执行多个操作。假设我想映射一个对象列表,但也要汇总所有对象的测量值。我想知道是否可以在不将数据转储到列表中的情况下执行此操作

Stream<Thing> thingStream = ...;
int accumulation = thingStream.mapToInt(Thing::measure).sum();
List<Another> results = thingStream.map(t -> toAnother(t)).collect(toList());
streamthingstream=。。。;
int累计=thingStream.mapToInt(Thing::measure.sum();
List results=thingStream.map(t->to other(t)).collect(toList());

我知道可以使用
Stream#peek
,但听起来有点骇人听闻。

您只能对一个流调用一个终端操作(例如:sum、count、collect…),因此答案是否定的,您不能使用同一个流来执行指定的两个不同的终端操作

这本书的小摘录说:

之后 执行终端操作时,应考虑流管道 已消耗,且不能再使用;如果您需要遍历相同的 同样,您必须返回数据源以获取新的 流动几乎在所有情况下,终端操作都是渴望完成的 它们遍历数据源和处理管道 回来之前。只有终端操作迭代器()和 拆分器()不是;这些都是作为“逃生舱口”提供的 在事件中启用任意客户端控制的管道遍历 现有操作不足以完成任务


每个终端操作都会向上调用源链的迭代器()。您只能调用一个终端操作,因为流不允许在其管道上进行多次遍历。这样做将导致
非法状态异常
。选择此选项是为了一致性目的,以支持一次性流源,如从网络读取文件或字节

请检查下面链接中的@StuartMarks答案


A
Stream
是一个潜在的无限数据源。是什么让你认为你可以不止一次地消费它?例如,我有一个来自恒温器的温度读数的
流,它们每毫秒一次可消费。流的元素在流的生命周期内只被访问一次。与迭代器一样,必须生成新的流以重新访问源代码的相同元素。“你是对的,你可以使用
peek(…)
来做你想做的事,但它确实是有漏洞的。
Stream#peek(…)
的文档说明“此方法的存在主要是为了支持调试”。所以不,你想要的是不可能的。