Correct pipelines give the same answer in parallel
forEachOrdered guarantees each action happens-before the next, so appending to one StringBuilder is safe there. With plain forEach it would not be.
Calling parallelStream() or .parallel() splits a stream's work across the threads of the shared fork/join pool. It gives the same answer as a sequential stream only if your operations are stateless, non-interfering and associative, and it's faster only for large, CPU-heavy work on sources that split well.
Change the code and press Run (Ctrl+Enter). Try to predict the output first, then break it on purpose and read the error. Your edits are saved and match the lesson page.
Practice questions
Write the code in the editor, run it, then open the model answer to compare.
Compute the number of primes below 200,000 with a parallel IntStream and a simple isPrime method, and check it equals the sequential count.
Fix this racy code without using any locks: int[] total = {0}; IntStream.rangeClosed(1, 1000).parallel().forEach(n -> total[0] += n);. Print the correct total.
Count words by length in parallel with groupingByConcurrent and print the result as a sorted map, for "a bb cc ddd e ff ggg hhhh".
Explain it without notes
How does a parallel stream split and execute work?
What conditions must a pipeline meet to give correct results in parallel?
When does a parallel stream actually make things faster, and when slower?
Why is blocking I/O inside a parallel stream a problem?
How do ordering guarantees differ between forEach, forEachOrdered, findFirst, findAny and toList in parallel?
Expected output
sequential sum: 500000500000
parallel sum: 500000500000
toList keeps encounter order: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
forEachOrdered: 1 2 3 4 5 6 7 8 9 10
joining: 1,2,3,4,5,6,7,8,9,10
findFirst: 37
isParallel: true