Can a Java 8 `Stream` be parallel without you even asking for it?

java, java-8, java-stream

Solution

First, through the lens of specification. Whether a stream is parallel or sequential is part of a stream's state. Stream-creation methods should specify whether they create a sequential or parallel stream (and most in the JDK do), but they are not required to say so. If your stream source doesn't say, don't assume. If someone passes you a stream, don't assume.

Parallel streams are allowed to fall back to sequential at their discretion (since a sequential implementation is a parallel implementation, just a potentially imperfect one); the opposite is not true.

Now, through the lens of implementation. In the stream-creation methods in Collections and other JDK classes, we stick to a discipline of "create a sequential stream unless the user explicitly asks for parallelism". (Other libraries, however, make different choices. If they're polite, they'll specify their behavior.)

The relationship between stream parallelism and Spliterator only goes in one direction. A Spliterator can refuse to split -- effectively denying any parallelism -- but it can't demand that a client split it. So an uncooperative Spliterator can undermine parallelism, but not determine it.

Problem

As I see it, the obvious code, when using Java 8 `Stream`s, whether they be "object" streams or primitive streams (that is, `IntStream` and friends) would be to just use: ``` someStreamableResource.stream().whatever() ``` But then, quite a few "streamable resources" also have `.parallelStream()`. What isn't clear when reading the javadoc is whether `.stream()` streams are always sequential, and whether `.parallelStream()` streams are always parallel... And then there is `Spliterator`, and in particular its `.characteristics()`, one of them being that it can be `CONCURRENT`, or even `IMMUTABLE`. My gut feeling is that in fact, whether a `Stream` can be, or not, parallel by default, or parallel at all, is guided by its underlying `Spliterator`... Am I on the right track? I have read, and read again, the javadocs, and still cannot come up with a clear answer to this question...

Original source