![Page 1: Java Parallel Streams Internals: Order of Results for](https://reader030.vdocuments.net/reader030/viewer/2022012606/619b1d510a2c4a4ffc60161b/html5/thumbnails/1.jpg)
Java Parallel Streams Internals:
Order of Results for OperationsDouglas C. Schmidt
www.dre.vanderbilt.edu/~schmidt
Professor of Computer Science
Institute for Software
Integrated Systems
Vanderbilt University
Nashville, Tennessee, USA
![Page 2: Java Parallel Streams Internals: Order of Results for](https://reader030.vdocuments.net/reader030/viewer/2022012606/619b1d510a2c4a4ffc60161b/html5/thumbnails/2.jpg)
2
• Understand parallel stream internals, e.g.
• Know what can change & what can’t
• Splitting, combining, & pooling mechanisms
• Order of processing
• Order of results
• Overview
• Collections that affect results order
• Operations that affect results order
Learning Objectives in this Part of the Lesson
![Page 3: Java Parallel Streams Internals: Order of Results for](https://reader030.vdocuments.net/reader030/viewer/2022012606/619b1d510a2c4a4ffc60161b/html5/thumbnails/3.jpg)
3
• Understand parallel stream internals, e.g.
• Know what can change & what can’t
• Splitting, combining, & pooling mechanisms
• Order of processing
• Order of results
• Overview
• Collections that affect results order
• Operations that affect results order
Learning Objectives in this Part of the LessonList<Integer> list =
Arrays.asList(1, 2, ...);
Integer[] doubledList = list
.parallelStream()
.distinct()
.filter(x -> x % 2 == 0)
.map(x -> x * 2)
.limit(sOutputLimit)
.toArray(Integer[]::new);
See github.com/douglascraigschmidt/LiveLessons/tree/master/Java8/ex21
Multiple examples are analyzed in detail
![Page 4: Java Parallel Streams Internals: Order of Results for](https://reader030.vdocuments.net/reader030/viewer/2022012606/619b1d510a2c4a4ffc60161b/html5/thumbnails/4.jpg)
4
Intermediate Operations that Affect Results Order
![Page 5: Java Parallel Streams Internals: Order of Results for](https://reader030.vdocuments.net/reader030/viewer/2022012606/619b1d510a2c4a4ffc60161b/html5/thumbnails/5.jpg)
5
• Certain intermediate operations affectordering behavior
Intermediate Operations that Affect Results Order…
Intermediate operation (behavior f)
Intermediate operation (behavior g)
Terminal operation (reducer)
Stream factory operation ()
Output
f(x)
Output
g(f(x))
Input x
![Page 6: Java Parallel Streams Internals: Order of Results for](https://reader030.vdocuments.net/reader030/viewer/2022012606/619b1d510a2c4a4ffc60161b/html5/thumbnails/6.jpg)
6
• Certain intermediate operations affectordering behavior
• e.g., sorted(), unordered(), skip(), & limit()
Intermediate Operations that Affect Results OrderList<Integer> list = Arrays
.asList(2, 3, 1, 4, 2);
Integer[] doubledList = list
.parallelStream()
.distinct()
.filter(x -> x % 2 == 0)
.map(x -> x * 2)
.limit(sOutputLimit)
.toArray(Integer[]::new);
See developer.ibm.com/languages/java/articles/j-java-streams-3-brian-goetz
![Page 7: Java Parallel Streams Internals: Order of Results for](https://reader030.vdocuments.net/reader030/viewer/2022012606/619b1d510a2c4a4ffc60161b/html5/thumbnails/7.jpg)
7Again, recall that “ordered” isn’t the same as “sorted”!
• Certain intermediate operations affectordering behavior
• e.g., sorted(), unordered(), skip(), & limit()
Intermediate Operations that Affect Results OrderList<Integer> list = Arrays
.asList(2, 3, 1, 4, 2);
Integer[] doubledList = list
.parallelStream()
.distinct()
.filter(x -> x % 2 == 0)
.map(x -> x * 2)
.limit(sOutputLimit)
.toArray(Integer[]::new);
The encounter order is [2, 3, 1, 4, 2] since list is ordered & non-unique
![Page 8: Java Parallel Streams Internals: Order of Results for](https://reader030.vdocuments.net/reader030/viewer/2022012606/619b1d510a2c4a4ffc60161b/html5/thumbnails/8.jpg)
8
• Certain intermediate operations affectordering behavior
• e.g., sorted(), unordered(), skip(), & limit()
Intermediate Operations that Affect Results Order
Remove duplicate elements from the stream (a stateful intermediate operation)
List<Integer> list = Arrays
.asList(2, 3, 1, 4, 2);
Integer[] doubledList = list
.parallelStream()
.distinct()
.filter(x -> x % 2 == 0)
.map(x -> x * 2)
.limit(sOutputLimit)
.toArray(Integer[]::new);
See docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#distinct
![Page 9: Java Parallel Streams Internals: Order of Results for](https://reader030.vdocuments.net/reader030/viewer/2022012606/619b1d510a2c4a4ffc60161b/html5/thumbnails/9.jpg)
9
• Certain intermediate operations affectordering behavior
• e.g., sorted(), unordered(), skip(), & limit()
Intermediate Operations that Affect Results OrderList<Integer> list = Arrays
.asList(2, 3, 1, 4, 2);
Integer[] doubledList = list
.parallelStream()
.distinct()
.filter(x -> x % 2 == 0)
.map(x -> x * 2)
.limit(sOutputLimit)
.toArray(Integer[]::new);
Only process sOutputLimit elements in the stream (a stateful intermediate operation)
See docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#limit
![Page 10: Java Parallel Streams Internals: Order of Results for](https://reader030.vdocuments.net/reader030/viewer/2022012606/619b1d510a2c4a4ffc60161b/html5/thumbnails/10.jpg)
10
• Certain intermediate operations affectordering behavior
• e.g., sorted(), unordered(), skip(), & limit()
Intermediate Operations that Affect Results Order
The result must be [4, 8], but the code is slow due to limit() & distinct() “stateful” semantics in parallel streams
List<Integer> list = Arrays
.asList(2, 3, 1, 4, 2);
Integer[] doubledList = list
.parallelStream()
.distinct()
.filter(x -> x % 2 == 0)
.map(x -> x * 2)
.limit(sOutputLimit)
.toArray(Integer[]::new);
![Page 11: Java Parallel Streams Internals: Order of Results for](https://reader030.vdocuments.net/reader030/viewer/2022012606/619b1d510a2c4a4ffc60161b/html5/thumbnails/11.jpg)
11
• Certain intermediate operations affectordering behavior
• e.g., sorted(), unordered(), skip(), & limit()
Intermediate Operations that Affect Results OrderList<Integer> list = Arrays
.asList(2, 3, 1, 4, 2);
Integer[] doubledList = list
.parallelStream()
.unordered()
.distinct()
.filter(x -> x % 2 == 0)
.map(x -> x * 2)
.limit(sOutputLimit)
.toArray(Integer[]::new);
This code runs faster since stream is unordered, so therefore limit() & distinct() incur less overhead
See docs.oracle.com/javase/8/docs/api/java/util/stream/BaseStream.html#unordered
![Page 12: Java Parallel Streams Internals: Order of Results for](https://reader030.vdocuments.net/reader030/viewer/2022012606/619b1d510a2c4a4ffc60161b/html5/thumbnails/12.jpg)
12
• Certain intermediate operations affectordering behavior
• e.g., sorted(), unordered(), skip(), & limit()
Intermediate Operations that Affect Results OrderList<Integer> list = Arrays
.asList(2, 3, 1, 4, 2);
Integer[] doubledList = list
.parallelStream()
.unordered()
.distinct()
.filter(x -> x % 2 == 0)
.map(x -> x * 2)
.limit(sOutputLimit)
.toArray(Integer[]::new);
Since encounter order needn’t be maintained the results could either be [8, 4] or [4, 8]
See developer.ibm.com/languages/java/articles/j-java-streams-3-brian-goetz
![Page 13: Java Parallel Streams Internals: Order of Results for](https://reader030.vdocuments.net/reader030/viewer/2022012606/619b1d510a2c4a4ffc60161b/html5/thumbnails/13.jpg)
13
Terminal Operations that Affect Results Order
![Page 14: Java Parallel Streams Internals: Order of Results for](https://reader030.vdocuments.net/reader030/viewer/2022012606/619b1d510a2c4a4ffc60161b/html5/thumbnails/14.jpg)
14
• Certain terminal operations also affectordering behavior
Terminal Operations that Affect Results Order…
Intermediate operation (behavior f)
Intermediate operation (behavior g)
Terminal operation (reducer)
Stream factory operation ()
Output
f(x)
Output
g(f(x))
Input x
![Page 15: Java Parallel Streams Internals: Order of Results for](https://reader030.vdocuments.net/reader030/viewer/2022012606/619b1d510a2c4a4ffc60161b/html5/thumbnails/15.jpg)
15
• Certain terminal operations also affectordering behavior, e.g.
• forEachOrdered()
Terminal Operations that Affect Results OrderList<Integer> list = Arrays
.asList(2, 3, 1, 4, 2);
List<Integer> results =
new ArrayList<>();
list
.parallelStream()
.distinct()
.filter(x -> x % 2 == 0)
.map(x -> x * 2)
.limit(sOutputLimit)
.forEachOrdered
(results::add);
The encounter order is [2, 3, 1, 4, 2] since list is ordered & non-unique.
![Page 16: Java Parallel Streams Internals: Order of Results for](https://reader030.vdocuments.net/reader030/viewer/2022012606/619b1d510a2c4a4ffc60161b/html5/thumbnails/16.jpg)
16
• Certain terminal operations also affectordering behavior, e.g.
• forEachOrdered()
Terminal Operations that Affect Results OrderList<Integer> list = Arrays
.asList(2, 3, 1, 4, 2);
List<Integer> results =
new ArrayList<>();
list
.parallelStream()
.distinct()
.filter(x -> x % 2 == 0)
.map(x -> x * 2)
.limit(sOutputLimit)
.forEachOrdered
(results::add);
This list supports unsynchronized insertions & removals of elements
![Page 17: Java Parallel Streams Internals: Order of Results for](https://reader030.vdocuments.net/reader030/viewer/2022012606/619b1d510a2c4a4ffc60161b/html5/thumbnails/17.jpg)
17
• Certain terminal operations also affectordering behavior, e.g.
• forEachOrdered()
Terminal Operations that Affect Results OrderList<Integer> list = Arrays
.asList(2, 3, 1, 4, 2);
List<Integer> results =
new ArrayList<>();
list
.parallelStream()
.distinct()
.filter(x -> x % 2 == 0)
.map(x -> x * 2)
.limit(sOutputLimit)
.forEachOrdered
(results::add);
Results must appear in encounter order, but may be slow due to implicit synchronization in forEachOrdered()
See docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#forEachOrdered
![Page 18: Java Parallel Streams Internals: Order of Results for](https://reader030.vdocuments.net/reader030/viewer/2022012606/619b1d510a2c4a4ffc60161b/html5/thumbnails/18.jpg)
18
• Certain terminal operations also affectordering behavior, e.g.
• forEachOrdered()
• forEach()
Terminal Operations that Affect Results OrderList<Integer> list = Arrays
.asList(2, 3, 1, 4, 2);
ConcurrentLinkedQueue
<Integer> results = new
ConcurrentLinkedQueue<>();
list
.parallelStream()
.distinct()
.filter(x -> x % 2 == 0)
.map(x -> x * 2)
.limit(sOutputLimit)
.forEach
(results::add);
Results need not appear in the encounter order, but may be faster since forEach() isn’t synchronized
See docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#forEach
![Page 19: Java Parallel Streams Internals: Order of Results for](https://reader030.vdocuments.net/reader030/viewer/2022012606/619b1d510a2c4a4ffc60161b/html5/thumbnails/19.jpg)
19
• Certain terminal operations also affectordering behavior, e.g.
• forEachOrdered()
• forEach()
Terminal Operations that Affect Results OrderList<Integer> list = Arrays
.asList(2, 3, 1, 4, 2);
ConcurrentLinkedQueue
<Integer> results = new
ConcurrentLinkedQueue<>();
list
.parallelStream()
.distinct()
.filter(x -> x % 2 == 0)
.map(x -> x * 2)
.limit(sOutputLimit)
.forEach
(results::add);
However, this collection must support thread-safe insertions & removals!!
See docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentLinkedQueue.html
![Page 20: Java Parallel Streams Internals: Order of Results for](https://reader030.vdocuments.net/reader030/viewer/2022012606/619b1d510a2c4a4ffc60161b/html5/thumbnails/20.jpg)
20
End of Java Parallel Streams Internals: Order of Results
for Operations