How to ensure order of processing in java8 streams?

java, java-8, java-stream

Solution

You are asking the wrong question. You are asking about `sequential` vs. `parallel` whereas you want to process items in order, so you have to ask about ordering. If you have an ordered stream and perform operations which guarantee to maintain the order, it doesn’t matter whether the stream is processed in parallel or sequential; the implementation will maintain the order.

The ordered property is distinct from parallel vs sequential. E.g. if you call `stream()` on a `HashSet` the stream will be unordered while calling `stream()` on a `List` returns an ordered stream. Note that you can call `unordered()` to release the ordering contract and potentially increase performance. Once the stream has no ordering there is no way to reestablish the ordering. (The only way to turn an unordered stream into an ordered is to call `sorted`, however, the resulting order is not necessarily the original order).

See also the “Ordering” section of the `java.util.stream` package documentation.

In order to ensure maintenance of ordering throughout an entire stream operation, you have to study the documentation of the stream’s source, all intermediate operations and the terminal operation for whether they maintain the order or not (or whether the source has an ordering in the first place).

This can be very subtle, e.g. `Stream.iterate(T,UnaryOperator)` creates an ordered stream while `Stream.generate(Supplier)` creates an unordered stream. Note that you also made a common mistake in your question as `forEach` does not maintain the ordering. You have to use `forEachOrdered` if you want to process the stream’s elements in a guaranteed order.

So if your `list` in your question is indeed a `java.util.List`, its `stream()` method will return an ordered stream and `filter` will not change the ordering. So if you call `list.stream().filter() .forEachOrdered()`, all elements will be processed sequentially in order, whereas for `list.parallelStream().filter().forEachOrdered()` the elements might be processed in parallel (e.g. by the filter) but the terminal action will still be called in order (which obviously will reduce the benefit of parallel execution).

If you, for example, use an operation like

List<…> result=inputList.parallelStream().map(…).filter(…).collect(Collectors.toList());

the entire operation might benefit from parallel execution but the resulting list will always be in the right order, regardless of whether you use a parallel or sequential stream.

Problem

I want to process lists inside an `XML` java object. I have to ensure processing all elements in order I received them. Should I therefore call `sequential` on each `stream` I use? `list.stream().sequential().filter().forEach()` Or it it sufficient to just use the stream as long as I don't use parallelism? `list.stream().filter().forEach()`

Original source

Related problems