Java Programs›Java 8 Streams›Calculate a Sum Using Parallel Streams

Calculate a Sum Using Parallel Streams in Java

advanced·  Java 8 Streams  ·  Streams

Problem

A parallel stream splits its work across several threads from the common ForkJoinPool and combines the partial results.

Sum the numbers from 1 to 10,000,000 sequentially and in parallel, and check both totals against the formula n(n + 1)/2.

Input
n = 10,000,000
Output
50000005000000

Java Program

Java
import java.util.stream.LongStream; public class ParallelStreamSum { public static void main(String[] args) { long n = 10_000_000; long sequential = LongStream.rangeClosed(1, n).sum(); long parallel = LongStream.rangeClosed(1, n).parallel().sum(); // split across CPU cores System.out.println("Sequential sum: " + sequential); System.out.println("Parallel sum: " + parallel); System.out.println("Same result: " + (sequential == parallel)); System.out.println("Formula check: " + n * (n + 1) / 2); } }

Output

Sequential sum: 50000005000000 Parallel sum: 50000005000000 Same result: true Formula check: 50000005000000

Core Logic

Calling parallel() changes how the stream runs, not what it computes — for an associative operation like addition, the result is identical.

How It Works
  1. 1LongStream.rangeClosed(1, n).sum() adds the numbers on one thread.
  2. 2.parallel() splits the range into chunks summed on several threads, then adds the chunk totals.
  3. 3long is needed, because the total exceeds the int range.
  4. 4The formula n(n + 1)/2 confirms the answer.
Both approaches produce 50000005000000.
💡

Key Point: Parallel streams pay off only for large, CPU-heavy, easily split work; for small lists the thread coordination costs more than it saves.

Complexity
Time Complexity: O(n)Space Complexity: O(1)

Why: Every number is added once in total; parallelism divides that work across cores rather than reducing it.

Key Concepts

parallel()LongStream.rangeClosed()associative operations

Approach 2: Keeping Order in Parallel

Java
import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; public class ParallelStreamOrder { public static void main(String[] args) { List<Integer> squares = IntStream.rangeClosed(1, 8) .parallel() .map(x -> x * x) .boxed() .collect(Collectors.toList()); // collect keeps the encounter order, even in parallel StringBuilder ordered = new StringBuilder(); IntStream.rangeClosed(1, 8).parallel() .forEachOrdered(x -> ordered.append(x).append(' ')); // forEach would not guarantee order System.out.println("Squares: " + squares); System.out.println("forEachOrdered: " + ordered.toString().trim()); } }

Output

Squares: [1, 4, 9, 16, 25, 36, 49, 64] forEachOrdered: 1 2 3 4 5 6 7 8

Core Logic

Parallel streams may process elements in any order, but collect and forEachOrdered still respect the original order.

How It Works
  1. 1map runs on several threads, yet collect(toList()) returns squares in order 1 to 8.
  2. 2forEachOrdered processes elements in their original order.
  3. 3Plain forEach on a parallel stream would print them in an unpredictable order.
Both lines come out in order 1 to 8 on every run.
💡

Key Point: If order matters, use forEachOrdered or collect first — and remember that enforcing order can cancel much of the parallel speed-up.

Complexity
Time Complexity: O(n)Space Complexity: O(n)

Why: Each element is processed once and stored in the result list.

Key Concepts

forEachOrdered()encounter ordercollect in parallel

Interview Questions

Which thread pool do parallel streams use?

The shared ForkJoinPool.commonPool(), whose size defaults to one less than the number of CPU cores.

Why is a parallel stream risky with shared mutable state?

Several threads may update the same variable at once, causing lost updates. Use reductions or collectors instead of writing to shared collections.

Learn the Concept

Related Programs