Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the reason "forEach" in Java Streams API is unordered? [duplicate]

As far as I'm aware, in parallel streams, methods such findFirst, skip, limit and etc. keep their behaviour as long as stream is ordered (which is by default) whether is't parallel or not. So I was wondering why forEach method is different. I gave it some thought, but I just could not understand the neccessity of defining forEachOrdered method, when it could have been more easier and less surprising to make forEach ordered by default, then call unordered on stream instance and that's it, no need to define new method.

Unfortunately my practical experience with Java 8 is quite limited at this point, so I would really appreciate if someone could explain me reasons for this architectural decision, maybe with some simple examples/use-cases to show me what could go wrong otherwise.

Just to make it clear, I'm not asking about this: forEach vs forEachOrdered in Java 8 Stream. I'm perfectly aware how those methods work and differences between them. What I'm asking about is practical reasons for architectural decision made by Oracle.

like image 258
Gaponenko Andrei Avatar asked Jan 02 '23 21:01

Gaponenko Andrei


2 Answers

Defining a method forEach that would preserve order and unordered that would break it, would complicated things IMO; simply because unordered does nothing more than setting a flag in the stream api internals and the flag checking would have to be performed or enforced based on some conditions.

So let's say you would do:

someStream()
      .unordered()
      .forEach(System.out::println)

In this case, your proposal is to not print elements in any order, thus enforcing unordered here. But what if we did:

someSet().stream()
         .unordered()
         .forEach(System.out::println)

In this case would you want unordered to be enforced? After all, the source of a stream is a Set, which has no order, so in this case, enforcing unordered is just useless; but this means additional tests on the source of the stream internally. This can get quite tricky and complicated (as it already is btw).

To make it simpler there were two method defined, that clearly stipulate what they will do; and this is on par for example with findFirst vs findAny or even Optional::isPresent and Optional::isEmpty (added in java-11).

like image 122
Eugene Avatar answered Feb 22 '23 16:02

Eugene


When you process elements of a Stream in parallel, you simply should not expect any guarantees on order.

The whole idea is that multiple threads work on different elements of that stream. They progress individually, therefore the order of processing is not predictable. It is indeterministic, aka random.

I could imagine that the people implementing that interface purposely give you random order, to make it really clear that you shall not expect any distinct order when using parallel streams.

like image 35
GhostCat Avatar answered Feb 22 '23 15:02

GhostCat