0

I understand that Java stream object doesn't allow forked stream. But it's also reasonable to imagine one would perform multiple actions to the same stream. Say I want to map a List of objects but also sum up a measurement across all objects. I'd like to know if it's possible to do so without dump data into a List.

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

I know it's possible to use Stream#peek but it sounds hacky.

ZDproject
  • 43
  • 5
  • A `Stream` is a potentially infinite source of data. What makes you think you can consume it more than once? For example, I have a `Stream` of tempreature readings from a thermostat, they come in every millisecond. – Boris the Spider Jul 03 '18 at 19:07
  • From [the documentation of `java.util.stream`](https://docs.oracle.com/javase/10/docs/api/java/util/stream/package-summary.html): "*Streams differ from collections in several ways: [...] Consumable. The elements of a stream are only visited once during the life of a stream. Like an Iterator, a new stream must be generated to revisit the same elements of the source.*" You are right, you could use `peek(...)` to do what you want, but it is hacky indeed. The documentation of `Stream#peek(...)` states that "*This method exists mainly to support debugging*". So no, what you want is not possible. – Turing85 Jul 03 '18 at 19:09

2 Answers2

0

You can call only one terminal operation (e.g: sum, count, collect .. ) on a stream, so the answer is no, you can not use the same stream to perform the 2 different terminal operations that you specified.

Small extract of the documentation says:

After the terminal operation is performed, the stream pipeline is considered consumed, and can no longer be used; if you need to traverse the same data source again, you must return to the data source to get a new stream. In almost all cases, terminal operations are eager, completing their traversal of the data source and processing of the pipeline before returning. Only the terminal operations iterator() and spliterator() are not; these are provided as an "escape hatch" to enable arbitrary client-controlled pipeline traversals in the event that the existing operations are not sufficient to the task.

NiVeR
  • 9,644
  • 4
  • 30
  • 35
0

Each terminal operation calls iterator() up the chain to the source .You can call only one terminal operation because Stream doesn't allow multiple traversal over its pipeline . Doing so will result in IllegalStateException .This has been chosen for consistency purpose to support one-shot stream sources like reading a file or bytes from a network .

Please check @StuartMarks answer in the below link

Why are Java Streams once-off?

Debapriya Biswas
  • 1,079
  • 11
  • 23