SlideShare a Scribd company logo
1 of 50
Download to read offline
Angelika Langer & Klaus Kreft
http://www.AngelikaLanger.com/
Java 8
Stream
Puzzlers
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (2)
what we will do in this talk
• look at some surprising / not so surprising behavior
• show some Java 8 stream source code
• have a vote about its behavior / output
• let the code run
• discuss the reasons / background
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (4)
speakers' relationship to topic
• independent trainer / consultant / author
– teaching C++ and Java for ~20 years
– curriculum of some challenging seminars
– providing consulting services for ~20 years
– JCP observer and Java champion since 2005
– authors of "Effective Java" column
– author of Java Generics FAQ and Lambda Tutorial & Reference
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (5)
let's get started ...
puzzler #1
parallel forEach()
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (9)
puzzler #1 – explained
• parallel !!!
• javadoc (forEach()):
The behavior of this operation is explicitly nondeterministic. For
parallel stream pipelines, this operation does not guarantee to
respect the encounter order of the stream, as doing so would
sacrifice the benefit of parallelism. For any given element, the
action may be performed at whatever time and in whatever thread
the library chooses. If the action accesses shared state, it is
responsible for providing the required synchronization.
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (10)
parallel forEach()
T
fork phase execution join phase
forEach(s -> System.out.print(s))
T2
T1
T22
T21
T12
T11
T2
T1
T
forEach(...)
forEach(...)
forEach(...)
forEach(...)
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (11)
let's use another stream operation ...
puzzler #2
parallel reduce()
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (15)
puzzler #2 – explained
• javadoc (reduce()):
T reduce(T identity, BinaryOperator<T> accumulator)
Performs a reduction on the elements of this stream, using the
provided identity value and an associative accumulation function,
and returns the reduced value. This is equivalent to:
T result = identity;
for (T element : this stream)
result = accumulator.apply(result, element)
return result;
but is not constrained to execute sequentially.
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (16)
puzzler #2 – explained (cont.)
• javadoc also says:
The identity value must be an identity for the accumulator
function. This means that for all t,
accumulator.apply(identity, t) is equal to t.
The accumulator function must be an associative function.
• these requirements are important
– ensure: order preserving when executed in parallel
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (17)
puzzler #2 – identity
• The identity value must be an identity for the
accumulator function. This means that for all t,
accumulator.apply(identity, t) is equal to t.
• our example
reduce("", (s1, s2) -> s1 + s2)
because: ("" + s).equals(s)
for all String s
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (18)
puzzler #2 – associative
• The accumulator function must be an associative function.
• commutative: op(a,b) = op(b,a) or a○b = b○a
– example: max for int, “+” for int
– associative: op(op(a,b),c) = op(a,op(b,c)) or
((a○b)○c) = (a○(b○c))
 example: “+” for String (string concatenation)
– "hello"+"world" differs from "world"+"hello"
– (("one"+"two")+"three") same as ("one"+("two"+"three"))
– example: “-” for int
3-1 differs from 1-3
((3-2)-1) differs from (3-(2-1))
notcommutative
notassociative
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (19)
puzzler #2 - requirements ignored
• what if we violate the requirements ... ?
– use non-identity
– use non-associative accumulator
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (20)
let's ignore identity ...
puzzler #2a
parallel reduce() - with non-identity
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (24)
parallel reduce()
T
fork phase execution join phase
T2
T1
T22
T21
T12
T11
T2
T1
T
"->" + ...
"->" + ...
"->" + ...
"->" + ...
reduce("->", (s1, s2) -> s1 + s2)
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (25)
puzzler #2 – violate associativity
• use as reduction operation
– where toggle() turns
 the upper case characters from s1 to lower case, and
 the lower case characters form s1 to upper case
reduce("", (s1, s2) -> toggle(s1) + s2)
String toggle(String in) {
char[] chars = in.toCharArray();
char[] buf = new char[chars.length];
for (int i=0;i<chars.length;i++) {
if (Character.isLowerCase(chars[i]))
buf[i] = Character.toUpperCase(chars[i]);
if (Character.isUpperCase(chars[i]))
buf[i] = Character.toLowerCase(chars[i]);
}
return new String(buf);
}
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (26)
puzzler #2 – violate associativity (cont.)
• use as reduction operation
– toggle() is not associative
 (a○b)○c -> Ab○c -> aBc
 a○(b○c) -> a○Bc -> ABc
reduce("", (s1, s2) -> toggle(s1) + s2)
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (27)
let's ignore associativity ...
puzzler #2b
parallel reduce() - non-associative accumulator
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (29)
parallel reduce()
T
fork phase execution join phase
T2
T1
T22
T21
T12
T11
T2
T1
T
toggle(t21) + t22
reduce("", (s1, s2) -> toggle(s1) + s2)
toggle(t11) + t12
toggle(t1) + t2
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (30)
parallel reduce()
• sequential reduce()
(((((((a○b)○c)○d)○e)○f)○g)○h) => AbCdEfGh
• parallel reduce() with split in halves
((a○b)○c)○d) ○ ((e○f)○g)○h) => aBcDEfGh
• parallel reduce() with split in quarters
((a○b) ○ (c○d)) ○ ((e○f) ○ (g○h)) => AbcDeFGh
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (31)
puzzler #2a/b – hint
• violating the accumulator requirements cause
the results produced by parallel streams to be wrong
• but also not okay for sequential streams
• extremely fragile code
– adding parallel() leads to wrong results
– can easily happen when the responsibility for code is shared
 typical for an agile process
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (32)
other stream sources
• streams can be generated
• stream operation generate()
… each element is generated by the provided Supplier .
static <T> Stream<T> generate(Supplier<T> s)
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (33)
let's use a generated stream ...
puzzler #3
generate()
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (37)
puzzler #3 – explained
• javadoc (generate()):
Returns an infinite sequential unordered stream where
each element is generated by the provided Supplier.
This is suitable for generating constant streams,
streams of random elements, etc.
• we have used generate() incorrectly
• as before: fails when executed in parallel
– but sequential code is fragile and also not recommended
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (38)
splitting unordered infinite streams
• unordered infinite streams have a special spliterator
– of type StreamSpliterators.UnorderedSliceSpliterator
• creates stream slices
– each slice is filled with generated elements
– concurrently by several threads
• each task
– iterates over a slice
– applies intermediate/terminal operation
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (39)
splitting infinite streams
...
slices are filled concurrently => unordered
generate(...).parallel().map(...).reduce(...)
1 2 3 4 5 6 7 8
1 2 4 6 3 5 7 8 910 11
map
reduce
slices are processed in parallel
i.e., sequentially per slice,
but multiple slices in parallel
35789...
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (40)
another stream generator
• stream operation iterate()
… iterative application of a function f to an initial element
seed, producing a Stream consisting of seed, f(seed),
f(f(seed)), etc.
static <T> Stream<T> iterate(T seed, UnaryOperator<T> f)
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (41)
let's use another stream generator ...
puzzler #4
iterate()
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (45)
puzzler #4 – explained
• javadoc (iterate()):
Returns an infinite sequential ordered Stream
produced by iterative application of a function f to an
initial element seed, producing a Stream consisting of
seed, f(seed), f(f(seed)), etc.
The first element (position 0) in the Stream will be the
provided seed. For n > 0, the element at position n,
will be the result of applying the function f to the
element at position n - 1.
• this time we have done it correctly
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (46)
splitting ordered infinite streams
• ordered infinite streams use a spliterator
– of type Spliterators.IteratorSpliterator
• creates batches
– each batch is filled with generated elements
– sequentially by one thread
not necessarily always the same thread
– next batch might be filled sequentially by another thread
• each task
– iterates over a segment of a batch
– applies intermediate/terminal operation
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (47)
splitting infinite streams
...
batches are filled sequentially => ordered
iterate(...).parallel().map(...).reduce(...)
1 2 3 4 5 6 7 8
1 2 3 4 5 6
map
reduce
batches are split and processed in parallel
i.e., sequentially per segment,
but multiple segments in parallel
........
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (48)
order hint
• stream source and terminal operation must be ordered
then the result/effect is ordered
• figure that out from the javadoc, or (some simple rules):
– arrays and all collections (except HashSet) are ordered
– terminal operations
 reduce(), forEachOrdered() are ordered
 forEach() unordered
 collect() depends on how Characteristics
Collector.Characteristics.UNORDERED and
Collector.Characteristics.CONCURRENT
are set for the Collector
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (49)
intermediate operations and order ...
puzzler #5
intermediate map()
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (54)
order hint: intermediate operations
• intermediate operations have no effect on order
• except:
– the intermediate operation sorted() restores order
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (55)
let's put order into an unordered source ...
puzzler #6
restoring order via sorted()
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (59)
puzzler #6 – explained
• unfortunately the javadoc (of sorted()) is not of much
help
• there is only a small hint:
This is a stateful intermediate operation.
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (60)
puzzler #6 – explained (cont.)
• need to have a look at the implemention
– sorted() is implemented with two barriers, i.e.
 stream elements are collected before the actual sort (1st barrier),
 then the sort is performed with the collected elements, and then
 the resulting elements are collected again after the sort (2nd barrier) ,
– before the next operations start
• first barrier leads (already) to OutOfMemoryError
– because it is an infinite stream that is generated()
.parallelStream().statelessOps().sorted().statelessOps().terminal();
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (61)
let's explore parallel() / sequential() ...
puzzler #7
parallel() and sequential()
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (67)
puzzler #7 – explained
• unfortunately the javadoc of sequential() is not of
much help
• there is only a small hint:
May return itself, either because the stream was already
sequential, or because the underlying stream state was
modified to be sequential.
• that’s how its done in (all) stream implementations
– parallel() / sequential() flip a flag (stream state)
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (68)
puzzler #7 – explained (cont.)
• and
– intermediate operations are lazy
 not executed immediately
– terminal operations are eager
 trigger the execution of all previous intermediate operations,
and the terminal operation
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (69)
pipeline
'a' 'b' 'c' 'd' 'e' 'f'
'A' 'B' 'C 'D' 'E' 'F'
code looks like
really executed
map
forEach
Arrays.stream(chars)
.map(s -> toggle(s))
.forEach(s -> System.out.print(s));
'A' 'B' 'C 'D' 'E' 'F'
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (70)
puzzler #7 – explained (cont.)
Arrays.stream(chars).parallel()
.map(s -> toggle(s))
.sequential()
.forEach(s -> System.out.print(s));
set parallel
set sequential
trigger all stream operations, with mode set to sequential
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (71)
difference between …
… stream operations and other methods
• stream operation act upon
the elements of the underlying stream source
– defined in Stream<T>, IntStream, LongStream, DoubleStream
• other operations
– stream maintenance / management
 e.g. parallel(), sequential()
– defined in BaseStream
 super-interface to Stream<T>, IntStream, LongStream, DoubleStream
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (72)
let's explore forEachOrdered() ...
puzzler #8
forEachOrdered()
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (76)
puzzler08 – why is it so
• this time we have done it correctly
• javadoc (forEachOdered()):
This operation processes the elements one at a time, in encounter
order if one exists.
• what the javadoc does not say:
often slower than forEach()
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (77)
forEachOrdered()
T
fork phase execution join phase
map(s->toggle(s)).forEachOrdered(s->System.out.println(s));
T2
T1
T22
T21
T12
T11
T2
T1
T
(map+forEachOrdered)T11
mapT12
mapT22
mapT21
forEachOrderedT12
forEachOrederedT2
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (78)
wrap-up
• preservation of encounter order requires:
– underlying stream source must be ordered, or
– intermediate operation sorted() creates order,
and
– terminal operation must be ordered
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (79)
wrap-up
• ordered stream sources
– arrays, collections (exception HashSet), iterate(), ...
• unordered stream sources
– HashSet, generate(), ...
• ordered terminal operations
– reduce(), forEachOrdered(), collect(toCollection()), ...
• unordered terminal operations
– forEach(), collect(toConcurrentMap()), ...
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (80)
authors
Angelika LangerAngelika Langer
KlausKlaus KreftKreft
www.AngelikaLanger.com
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (81)
stream puzzlers
Q & A
© Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved.
http://www.AngelikaLanger.com/
last update: 4/4/2017,18:28
stream puzzlers (82)
source code
www.AngelikaLanger.comConferencesCodejDays2017Main.java

More Related Content

What's hot

Simseer.com - Malware Similarity and Clustering Made Easy
Simseer.com - Malware Similarity and Clustering Made EasySimseer.com - Malware Similarity and Clustering Made Easy
Simseer.com - Malware Similarity and Clustering Made Easy
Silvio Cesare
 
Evolution of asynchrony in (ASP).NET
Evolution of asynchrony in (ASP).NETEvolution of asynchrony in (ASP).NET
Evolution of asynchrony in (ASP).NET
Aliaksandr Famin
 
Swift で数学のススメ 〜 プログラミングと数学は同時に学べ
Swift で数学のススメ 〜 プログラミングと数学は同時に学べSwift で数学のススメ 〜 プログラミングと数学は同時に学べ
Swift で数学のススメ 〜 プログラミングと数学は同時に学べ
Taketo Sano
 
Functional Reactive Programming / Compositional Event Systems
Functional Reactive Programming / Compositional Event SystemsFunctional Reactive Programming / Compositional Event Systems
Functional Reactive Programming / Compositional Event Systems
Leonardo Borges
 

What's hot (20)

RxJava applied [JavaDay Kyiv 2016]
RxJava applied [JavaDay Kyiv 2016]RxJava applied [JavaDay Kyiv 2016]
RxJava applied [JavaDay Kyiv 2016]
 
Simseer.com - Malware Similarity and Clustering Made Easy
Simseer.com - Malware Similarity and Clustering Made EasySimseer.com - Malware Similarity and Clustering Made Easy
Simseer.com - Malware Similarity and Clustering Made Easy
 
Asynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFutureAsynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFuture
 
Evolution of asynchrony in (ASP).NET
Evolution of asynchrony in (ASP).NETEvolution of asynchrony in (ASP).NET
Evolution of asynchrony in (ASP).NET
 
Predictive Datacenter Analytics with Strymon
Predictive Datacenter Analytics with StrymonPredictive Datacenter Analytics with Strymon
Predictive Datacenter Analytics with Strymon
 
Swift で数学のススメ 〜 プログラミングと数学は同時に学べ
Swift で数学のススメ 〜 プログラミングと数学は同時に学べSwift で数学のススメ 〜 プログラミングと数学は同時に学べ
Swift で数学のススメ 〜 プログラミングと数学は同時に学べ
 
Distributed Consensus A.K.A. "What do we eat for lunch?"
Distributed Consensus A.K.A. "What do we eat for lunch?"Distributed Consensus A.K.A. "What do we eat for lunch?"
Distributed Consensus A.K.A. "What do we eat for lunch?"
 
An Introduction to RxJava
An Introduction to RxJavaAn Introduction to RxJava
An Introduction to RxJava
 
Lambda and Stream Master class - part 1
Lambda and Stream Master class - part 1Lambda and Stream Master class - part 1
Lambda and Stream Master class - part 1
 
Mikio Braun – Data flow vs. procedural programming
Mikio Braun – Data flow vs. procedural programming Mikio Braun – Data flow vs. procedural programming
Mikio Braun – Data flow vs. procedural programming
 
Functional Reactive Programming / Compositional Event Systems
Functional Reactive Programming / Compositional Event SystemsFunctional Reactive Programming / Compositional Event Systems
Functional Reactive Programming / Compositional Event Systems
 
RxJS - The Reactive Extensions for JavaScript
RxJS - The Reactive Extensions for JavaScriptRxJS - The Reactive Extensions for JavaScript
RxJS - The Reactive Extensions for JavaScript
 
R and C++
R and C++R and C++
R and C++
 
CS253: Priority queues (2019)
CS253: Priority queues (2019)CS253: Priority queues (2019)
CS253: Priority queues (2019)
 
Apache Flink @ NYC Flink Meetup
Apache Flink @ NYC Flink MeetupApache Flink @ NYC Flink Meetup
Apache Flink @ NYC Flink Meetup
 
Real world functional reactive programming
Real world functional reactive programmingReal world functional reactive programming
Real world functional reactive programming
 
Hot Streaming Java
Hot Streaming JavaHot Streaming Java
Hot Streaming Java
 
Introduction to Apache Flink
Introduction to Apache FlinkIntroduction to Apache Flink
Introduction to Apache Flink
 
Functional Reactive Programming in Clojurescript
Functional Reactive Programming in ClojurescriptFunctional Reactive Programming in Clojurescript
Functional Reactive Programming in Clojurescript
 
Lean way write asynchronous code with Kotlin’s coroutines - Ronen Sabag, Gett
Lean way write asynchronous code with Kotlin’s coroutines - Ronen Sabag, GettLean way write asynchronous code with Kotlin’s coroutines - Ronen Sabag, Gett
Lean way write asynchronous code with Kotlin’s coroutines - Ronen Sabag, Gett
 

Similar to Stream Puzzlers – Traps and Pitfalls in Using Java 8 Streams

Reactive Stream Processing with Akka Streams
Reactive Stream Processing with Akka StreamsReactive Stream Processing with Akka Streams
Reactive Stream Processing with Akka Streams
Konrad Malawski
 

Similar to Stream Puzzlers – Traps and Pitfalls in Using Java 8 Streams (20)

LINEデリマでのElasticsearchの運用と監視の話
LINEデリマでのElasticsearchの運用と監視の話LINEデリマでのElasticsearchの運用と監視の話
LINEデリマでのElasticsearchの運用と監視の話
 
Golang Performance : microbenchmarks, profilers, and a war story
Golang Performance : microbenchmarks, profilers, and a war storyGolang Performance : microbenchmarks, profilers, and a war story
Golang Performance : microbenchmarks, profilers, and a war story
 
🎶🎵Bo-stream-ian Rhapsody: A Musical Demo of Kafka Connect and Kafka Streams 🎵🎶
🎶🎵Bo-stream-ian Rhapsody: A Musical Demo of Kafka Connect and Kafka Streams 🎵🎶🎶🎵Bo-stream-ian Rhapsody: A Musical Demo of Kafka Connect and Kafka Streams 🎵🎶
🎶🎵Bo-stream-ian Rhapsody: A Musical Demo of Kafka Connect and Kafka Streams 🎵🎶
 
Programming with Lambda Expressions in Java
Programming with Lambda Expressions in Java Programming with Lambda Expressions in Java
Programming with Lambda Expressions in Java
 
How to tune Kafka® for production
How to tune Kafka® for productionHow to tune Kafka® for production
How to tune Kafka® for production
 
Fast and Reliable Apache Spark SQL Engine
Fast and Reliable Apache Spark SQL EngineFast and Reliable Apache Spark SQL Engine
Fast and Reliable Apache Spark SQL Engine
 
St Petersburg R user group meetup 2, Parallel R
St Petersburg R user group meetup 2, Parallel RSt Petersburg R user group meetup 2, Parallel R
St Petersburg R user group meetup 2, Parallel R
 
Tuga IT 2018 Summer Edition - The Future of C#
Tuga IT 2018 Summer Edition - The Future of C#Tuga IT 2018 Summer Edition - The Future of C#
Tuga IT 2018 Summer Edition - The Future of C#
 
Reactive Streams / Akka Streams - GeeCON Prague 2014
Reactive Streams / Akka Streams - GeeCON Prague 2014Reactive Streams / Akka Streams - GeeCON Prague 2014
Reactive Streams / Akka Streams - GeeCON Prague 2014
 
GraphConnect 2014 SF: Neo4j at Scale using Enterprise Integration Patterns
GraphConnect 2014 SF: Neo4j at Scale using Enterprise Integration PatternsGraphConnect 2014 SF: Neo4j at Scale using Enterprise Integration Patterns
GraphConnect 2014 SF: Neo4j at Scale using Enterprise Integration Patterns
 
Micro-Benchmarking Considered Harmful
Micro-Benchmarking Considered HarmfulMicro-Benchmarking Considered Harmful
Micro-Benchmarking Considered Harmful
 
MLflow with R
MLflow with RMLflow with R
MLflow with R
 
Networks and Types - the Future of Akka @ ScalaDays NYC 2018
Networks and Types - the Future of Akka @ ScalaDays NYC 2018Networks and Types - the Future of Akka @ ScalaDays NYC 2018
Networks and Types - the Future of Akka @ ScalaDays NYC 2018
 
Reactive Stream Processing with Akka Streams
Reactive Stream Processing with Akka StreamsReactive Stream Processing with Akka Streams
Reactive Stream Processing with Akka Streams
 
Kyo - Functional Scala 2023.pdf
Kyo - Functional Scala 2023.pdfKyo - Functional Scala 2023.pdf
Kyo - Functional Scala 2023.pdf
 
Kotlin boost yourproductivity
Kotlin boost yourproductivityKotlin boost yourproductivity
Kotlin boost yourproductivity
 
Serial-War
Serial-WarSerial-War
Serial-War
 
Atmosphere Conference 2015: Need for Async: In pursuit of scalable internet-s...
Atmosphere Conference 2015: Need for Async: In pursuit of scalable internet-s...Atmosphere Conference 2015: Need for Async: In pursuit of scalable internet-s...
Atmosphere Conference 2015: Need for Async: In pursuit of scalable internet-s...
 
What`s New in Java 8
What`s New in Java 8What`s New in Java 8
What`s New in Java 8
 
Streaming all the things with akka streams
Streaming all the things with akka streams   Streaming all the things with akka streams
Streaming all the things with akka streams
 

Recently uploaded

Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
masabamasaba
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
masabamasaba
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
VictorSzoltysek
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
VictoriaMetrics
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
masabamasaba
 

Recently uploaded (20)

%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
 

Stream Puzzlers – Traps and Pitfalls in Using Java 8 Streams

  • 1. Angelika Langer & Klaus Kreft http://www.AngelikaLanger.com/ Java 8 Stream Puzzlers
  • 2. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (2) what we will do in this talk • look at some surprising / not so surprising behavior • show some Java 8 stream source code • have a vote about its behavior / output • let the code run • discuss the reasons / background
  • 3. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (4) speakers' relationship to topic • independent trainer / consultant / author – teaching C++ and Java for ~20 years – curriculum of some challenging seminars – providing consulting services for ~20 years – JCP observer and Java champion since 2005 – authors of "Effective Java" column – author of Java Generics FAQ and Lambda Tutorial & Reference
  • 4. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (5) let's get started ... puzzler #1 parallel forEach()
  • 5. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (9) puzzler #1 – explained • parallel !!! • javadoc (forEach()): The behavior of this operation is explicitly nondeterministic. For parallel stream pipelines, this operation does not guarantee to respect the encounter order of the stream, as doing so would sacrifice the benefit of parallelism. For any given element, the action may be performed at whatever time and in whatever thread the library chooses. If the action accesses shared state, it is responsible for providing the required synchronization.
  • 6. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (10) parallel forEach() T fork phase execution join phase forEach(s -> System.out.print(s)) T2 T1 T22 T21 T12 T11 T2 T1 T forEach(...) forEach(...) forEach(...) forEach(...)
  • 7. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (11) let's use another stream operation ... puzzler #2 parallel reduce()
  • 8. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (15) puzzler #2 – explained • javadoc (reduce()): T reduce(T identity, BinaryOperator<T> accumulator) Performs a reduction on the elements of this stream, using the provided identity value and an associative accumulation function, and returns the reduced value. This is equivalent to: T result = identity; for (T element : this stream) result = accumulator.apply(result, element) return result; but is not constrained to execute sequentially.
  • 9. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (16) puzzler #2 – explained (cont.) • javadoc also says: The identity value must be an identity for the accumulator function. This means that for all t, accumulator.apply(identity, t) is equal to t. The accumulator function must be an associative function. • these requirements are important – ensure: order preserving when executed in parallel
  • 10. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (17) puzzler #2 – identity • The identity value must be an identity for the accumulator function. This means that for all t, accumulator.apply(identity, t) is equal to t. • our example reduce("", (s1, s2) -> s1 + s2) because: ("" + s).equals(s) for all String s
  • 11. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (18) puzzler #2 – associative • The accumulator function must be an associative function. • commutative: op(a,b) = op(b,a) or a○b = b○a – example: max for int, “+” for int – associative: op(op(a,b),c) = op(a,op(b,c)) or ((a○b)○c) = (a○(b○c))  example: “+” for String (string concatenation) – "hello"+"world" differs from "world"+"hello" – (("one"+"two")+"three") same as ("one"+("two"+"three")) – example: “-” for int 3-1 differs from 1-3 ((3-2)-1) differs from (3-(2-1)) notcommutative notassociative
  • 12. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (19) puzzler #2 - requirements ignored • what if we violate the requirements ... ? – use non-identity – use non-associative accumulator
  • 13. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (20) let's ignore identity ... puzzler #2a parallel reduce() - with non-identity
  • 14. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (24) parallel reduce() T fork phase execution join phase T2 T1 T22 T21 T12 T11 T2 T1 T "->" + ... "->" + ... "->" + ... "->" + ... reduce("->", (s1, s2) -> s1 + s2)
  • 15. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (25) puzzler #2 – violate associativity • use as reduction operation – where toggle() turns  the upper case characters from s1 to lower case, and  the lower case characters form s1 to upper case reduce("", (s1, s2) -> toggle(s1) + s2) String toggle(String in) { char[] chars = in.toCharArray(); char[] buf = new char[chars.length]; for (int i=0;i<chars.length;i++) { if (Character.isLowerCase(chars[i])) buf[i] = Character.toUpperCase(chars[i]); if (Character.isUpperCase(chars[i])) buf[i] = Character.toLowerCase(chars[i]); } return new String(buf); }
  • 16. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (26) puzzler #2 – violate associativity (cont.) • use as reduction operation – toggle() is not associative  (a○b)○c -> Ab○c -> aBc  a○(b○c) -> a○Bc -> ABc reduce("", (s1, s2) -> toggle(s1) + s2)
  • 17. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (27) let's ignore associativity ... puzzler #2b parallel reduce() - non-associative accumulator
  • 18. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (29) parallel reduce() T fork phase execution join phase T2 T1 T22 T21 T12 T11 T2 T1 T toggle(t21) + t22 reduce("", (s1, s2) -> toggle(s1) + s2) toggle(t11) + t12 toggle(t1) + t2
  • 19. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (30) parallel reduce() • sequential reduce() (((((((a○b)○c)○d)○e)○f)○g)○h) => AbCdEfGh • parallel reduce() with split in halves ((a○b)○c)○d) ○ ((e○f)○g)○h) => aBcDEfGh • parallel reduce() with split in quarters ((a○b) ○ (c○d)) ○ ((e○f) ○ (g○h)) => AbcDeFGh
  • 20. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (31) puzzler #2a/b – hint • violating the accumulator requirements cause the results produced by parallel streams to be wrong • but also not okay for sequential streams • extremely fragile code – adding parallel() leads to wrong results – can easily happen when the responsibility for code is shared  typical for an agile process
  • 21. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (32) other stream sources • streams can be generated • stream operation generate() … each element is generated by the provided Supplier . static <T> Stream<T> generate(Supplier<T> s)
  • 22. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (33) let's use a generated stream ... puzzler #3 generate()
  • 23. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (37) puzzler #3 – explained • javadoc (generate()): Returns an infinite sequential unordered stream where each element is generated by the provided Supplier. This is suitable for generating constant streams, streams of random elements, etc. • we have used generate() incorrectly • as before: fails when executed in parallel – but sequential code is fragile and also not recommended
  • 24. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (38) splitting unordered infinite streams • unordered infinite streams have a special spliterator – of type StreamSpliterators.UnorderedSliceSpliterator • creates stream slices – each slice is filled with generated elements – concurrently by several threads • each task – iterates over a slice – applies intermediate/terminal operation
  • 25. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (39) splitting infinite streams ... slices are filled concurrently => unordered generate(...).parallel().map(...).reduce(...) 1 2 3 4 5 6 7 8 1 2 4 6 3 5 7 8 910 11 map reduce slices are processed in parallel i.e., sequentially per slice, but multiple slices in parallel 35789...
  • 26. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (40) another stream generator • stream operation iterate() … iterative application of a function f to an initial element seed, producing a Stream consisting of seed, f(seed), f(f(seed)), etc. static <T> Stream<T> iterate(T seed, UnaryOperator<T> f)
  • 27. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (41) let's use another stream generator ... puzzler #4 iterate()
  • 28. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (45) puzzler #4 – explained • javadoc (iterate()): Returns an infinite sequential ordered Stream produced by iterative application of a function f to an initial element seed, producing a Stream consisting of seed, f(seed), f(f(seed)), etc. The first element (position 0) in the Stream will be the provided seed. For n > 0, the element at position n, will be the result of applying the function f to the element at position n - 1. • this time we have done it correctly
  • 29. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (46) splitting ordered infinite streams • ordered infinite streams use a spliterator – of type Spliterators.IteratorSpliterator • creates batches – each batch is filled with generated elements – sequentially by one thread not necessarily always the same thread – next batch might be filled sequentially by another thread • each task – iterates over a segment of a batch – applies intermediate/terminal operation
  • 30. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (47) splitting infinite streams ... batches are filled sequentially => ordered iterate(...).parallel().map(...).reduce(...) 1 2 3 4 5 6 7 8 1 2 3 4 5 6 map reduce batches are split and processed in parallel i.e., sequentially per segment, but multiple segments in parallel ........
  • 31. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (48) order hint • stream source and terminal operation must be ordered then the result/effect is ordered • figure that out from the javadoc, or (some simple rules): – arrays and all collections (except HashSet) are ordered – terminal operations  reduce(), forEachOrdered() are ordered  forEach() unordered  collect() depends on how Characteristics Collector.Characteristics.UNORDERED and Collector.Characteristics.CONCURRENT are set for the Collector
  • 32. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (49) intermediate operations and order ... puzzler #5 intermediate map()
  • 33. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (54) order hint: intermediate operations • intermediate operations have no effect on order • except: – the intermediate operation sorted() restores order
  • 34. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (55) let's put order into an unordered source ... puzzler #6 restoring order via sorted()
  • 35. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (59) puzzler #6 – explained • unfortunately the javadoc (of sorted()) is not of much help • there is only a small hint: This is a stateful intermediate operation.
  • 36. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (60) puzzler #6 – explained (cont.) • need to have a look at the implemention – sorted() is implemented with two barriers, i.e.  stream elements are collected before the actual sort (1st barrier),  then the sort is performed with the collected elements, and then  the resulting elements are collected again after the sort (2nd barrier) , – before the next operations start • first barrier leads (already) to OutOfMemoryError – because it is an infinite stream that is generated() .parallelStream().statelessOps().sorted().statelessOps().terminal();
  • 37. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (61) let's explore parallel() / sequential() ... puzzler #7 parallel() and sequential()
  • 38. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (67) puzzler #7 – explained • unfortunately the javadoc of sequential() is not of much help • there is only a small hint: May return itself, either because the stream was already sequential, or because the underlying stream state was modified to be sequential. • that’s how its done in (all) stream implementations – parallel() / sequential() flip a flag (stream state)
  • 39. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (68) puzzler #7 – explained (cont.) • and – intermediate operations are lazy  not executed immediately – terminal operations are eager  trigger the execution of all previous intermediate operations, and the terminal operation
  • 40. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (69) pipeline 'a' 'b' 'c' 'd' 'e' 'f' 'A' 'B' 'C 'D' 'E' 'F' code looks like really executed map forEach Arrays.stream(chars) .map(s -> toggle(s)) .forEach(s -> System.out.print(s)); 'A' 'B' 'C 'D' 'E' 'F'
  • 41. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (70) puzzler #7 – explained (cont.) Arrays.stream(chars).parallel() .map(s -> toggle(s)) .sequential() .forEach(s -> System.out.print(s)); set parallel set sequential trigger all stream operations, with mode set to sequential
  • 42. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (71) difference between … … stream operations and other methods • stream operation act upon the elements of the underlying stream source – defined in Stream<T>, IntStream, LongStream, DoubleStream • other operations – stream maintenance / management  e.g. parallel(), sequential() – defined in BaseStream  super-interface to Stream<T>, IntStream, LongStream, DoubleStream
  • 43. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (72) let's explore forEachOrdered() ... puzzler #8 forEachOrdered()
  • 44. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (76) puzzler08 – why is it so • this time we have done it correctly • javadoc (forEachOdered()): This operation processes the elements one at a time, in encounter order if one exists. • what the javadoc does not say: often slower than forEach()
  • 45. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (77) forEachOrdered() T fork phase execution join phase map(s->toggle(s)).forEachOrdered(s->System.out.println(s)); T2 T1 T22 T21 T12 T11 T2 T1 T (map+forEachOrdered)T11 mapT12 mapT22 mapT21 forEachOrderedT12 forEachOrederedT2
  • 46. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (78) wrap-up • preservation of encounter order requires: – underlying stream source must be ordered, or – intermediate operation sorted() creates order, and – terminal operation must be ordered
  • 47. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (79) wrap-up • ordered stream sources – arrays, collections (exception HashSet), iterate(), ... • unordered stream sources – HashSet, generate(), ... • ordered terminal operations – reduce(), forEachOrdered(), collect(toCollection()), ... • unordered terminal operations – forEach(), collect(toConcurrentMap()), ...
  • 48. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (80) authors Angelika LangerAngelika Langer KlausKlaus KreftKreft www.AngelikaLanger.com
  • 49. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (81) stream puzzlers Q & A
  • 50. © Copyright 2003-2016 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 4/4/2017,18:28 stream puzzlers (82) source code www.AngelikaLanger.comConferencesCodejDays2017Main.java