Chapter 9. Parallel Streams

9.1.  Develop the code that use parallel streams

[Note]

Parallel Streams

Streams can be sequential or parallel. Operations on a sequential stream are processed in serial using one thread. Operations on a parallel stream are processed in parallel using multiple threads. You do not need to take additional steps to process streams because they are sequential or parallel. All you need to do is call the appropriate method that produces sequential or parallel stream. Everything else is taken care of by the Streams API

Most of the methods in the Streams API produce sequential streams by default. To produce a parallel stream from a collection such as a List or a Set, you need to call the parallelStream() method of the Collection interface.

Use the parallel() method on a stream to convert a sequential stream into a parallel stream. Conversely, use the sequential() method on a stream to convert a parallel stream into a sequential stream.

The following snippet of code shows serial processing of the stream pipeline because the stream is sequential:


List<Integer> listOfIntegers = List.of(1, 2, 3, 4, 5, 6, 7, 8);

System.out.println("Sequential Stream: ");
listOfIntegers
    .stream()
    .forEach(e -> System.out.print(e + " "));

					

output is:

Sequential Stream:
1 2 3 4 5 6 7 8
					

The following snippet of code shows parallel processing of the stream pipeline because the stream is parallel:


List<Integer> listOfIntegers = List.of(1, 2, 3, 4, 5, 6, 7, 8);

System.out.println("Parallel Stream: ");
listOfIntegers
    .stream()
    .parallel()
    .forEach(e -> System.out.print(e + " "));

					

output is (every time new order):

Parallel Stream:
6 5 7 4 2 1 8 3
					

You could also use this code:

...
listOfIntegers
    .parallelStream()
    .forEach(e -> System.out.print(e + " "));
...
					

[Important]

Besides being parallel or sequential, a stream also can be ordered or unordered.

Streams may or may not have a defined encounter order. Whether or not a stream has an encounter order depends on the source and the intermediate operations. Certain stream sources (such as List or arrays) are intrinsically ordered, whereas others (such as HashSet) are not. Some intermediate operations, such as sorted(), may impose an encounter order on an otherwise unordered stream, and others may render an ordered stream unordered, such as BaseStream.unordered(). Further, some terminal operations may ignore encounter order, such as forEach().

If a stream is ordered, most operations are constrained to operate on the elements in their encounter order; if the source of a stream is a List containing [1, 2, 3], then the result of executing map(x -> x*2) must be [2, 4, 6]. However, if the source has no defined encounter order, then any permutation of the values [2, 4, 6] would be a valid result.

For sequential streams, the presence or absence of an encounter order does not affect performance, only determinism. If a stream is ordered, repeated execution of identical stream pipelines on an identical source will produce an identical result; if it is not ordered, repeated execution might produce different results.

For parallel streams, relaxing the ordering constraint can sometimes enable more efficient execution. Certain aggregate operations, such as filtering duplicates (distinct()) or grouped reductions (Collectors.groupingBy()) can be implemented more efficiently if ordering of elements is not relevant. Similarly, operations that are intrinsically tied to encounter order, such as limit(), may require buffering to ensure proper ordering, undermining the benefit of parallelism. In cases where the stream has an encounter order, but the user does not particularly care about that encounter order, explicitly de-ordering the stream with unordered() may improve parallel performance for some stateful or terminal operations. However, most stream pipelines, such as the "sum of weight of blocks" example above, still parallelize efficiently even under ordering constraints.

Professional hosting         Exam 1Z0-817: Upgrade OCP Java 6, 7 & 8 to Java SE 11 Developer Quiz     Exam 1Z0-810: Upgrade to Java SE 8 Programmer Quiz