Parallel-Ready Java Code: Managing Mutation in an Imperative Language

212
Parallel-Ready Java Code Managing Mutation in an Imperative Language JavaDay Kyiv Nov 2015 #parallelready @mauricenaftalin

Transcript of Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Page 1: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Parallel-Ready Java CodeManaging Mutation in an Imperative Language

JavaDay KyivNov 2015

#parallelready@mauricenaftalin

Page 2: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Maurice Naftalin

Developer, designer, architect, teacher, learner, writer

Page 3: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Maurice Naftalin

Developer, designer, architect, teacher, learner, writer

JavaOne Rock Star

Java Champion

Page 4: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Repeat offender:

Maurice Naftalin

Page 5: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Repeat offender:

Maurice NaftalinJava 5

Page 6: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Repeat offender:

Maurice NaftalinJava 5 Java 8

Page 7: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

The Lambda FAQ

www.lambdafaq.org

Page 8: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Ideas in the Stream API

– Pipes/Filters

– Parallelism

• Recursive decomposition

• Stream-transforming (aka intermediate) operations

• Parallel merging

Page 9: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Pipes and Filters

• Venerable Unix tool-building pattern:ps -ef | grep login | cut -c 50- | head

• and in Enterprise Integration Patterns

Page 10: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Advantages of this pattern

Pipes and Filters

Page 11: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

ps -ef | grep login | cut -c 50- | head

Advantages of this pattern

Pipes and Filters

Page 12: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

- no intermediate variables

ps -ef | grep login | cut -c 50- | head

Advantages of this pattern

Pipes and Filters

Page 13: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

- no intermediate variables

- less (or no) intermediate storage

ps -ef | grep login | cut -c 50- | head

Advantages of this pattern

Pipes and Filters

Page 14: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

- no intermediate variables

- less (or no) intermediate storage

- lazy evaluation

ps -ef | grep login | cut -c 50- | head

Advantages of this pattern

Pipes and Filters

Page 15: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

- no intermediate variables

- less (or no) intermediate storage

- lazy evaluation

- flexible tool-building:

ps -ef | grep login | cut -c 50- | head

Advantages of this pattern

Pipes and Filters

Page 16: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Pipes and Filters

Doug McIlroy, inventor of the Unix pipe:

Page 17: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Pipes and Filters

Write programs that do one thing well.

Doug McIlroy, inventor of the Unix pipe:

Page 18: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Pipes and Filters

Write programs that do one thing well.Write programs to work together.

Doug McIlroy, inventor of the Unix pipe:

Page 19: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Pipes and Filters

Write programs that do one thing well.Write programs to work together.

Write programs to handle text streams

Doug McIlroy, inventor of the Unix pipe:

Page 20: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Pipes and Filters

Write programs that do one thing well.Write programs to work together.

Write programs to handle text streams

Doug McIlroy, inventor of the Unix pipe:

XXXXXXXX

Page 21: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Pipes and Filters

Write programs that do one thing well.Write programs to work together.

Write programs to handle text streams

Doug McIlroy, inventor of the Unix pipe:

XXXXXXXX

value objects and primitives

Page 22: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Example Domain

city: City name: Stringage: int

Person

Person amy = new Person(Athens, "Amy", 21); ...

List<Person> people = Arrays.asList(jon, amy, bill);

Page 23: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Pipes and Filters in Java

boolean allAdults = people.stream() .mapToInt(Person::getAge) .allMatch(a -> a >= 21);

Is everyone an adult?

Page 24: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Pipes and Filters in Java

boolean allAdults = people.stream() .mapToInt(Person::getAge) .allMatch(a -> a >= 21);

people.stream() .map(Person::getCity) .forEach(System.out::println);

Is everyone an adult?

Print the names ofthe inhabited cities

Page 25: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Streams

Sequence of values

• Not a collection — may be partially evaluated or exhausted

• Like an iterator, yielding elements for processing

• Not like an iterator, not associated with any storage mechanism

• Sources: collections, arrays, generators, IO channels

• Can be

- parallel

- infinite

• Primitive specialisations: IntStream, LongStream, DoubleStream

Page 26: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Sources – sequential streams

Stream Sources: – supply elements one at a time– implementations of java.util.Spliterator – 40+ methods in platform classes

– including Collection.stream

boolean allAdults = people.stream() .mapToInt(Person::getAge) .allMatch(a -> a >= 21);

Page 27: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Intermediate Operations

Filtering filter()

Mapping map()

One-to-Many Mapping flatMap()

Debugging peek()

Sorting/Deduplicating sorted(), distinct()

Truncating skip(), limit()

Page 28: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

filter(s -> s.length() < 4)

Stream<String>

Predicate<String

Stream<String>

filter()

Page 29: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

filter(s -> s.length() < 4)

Stream<String>

Predicate<String

Stream<String>

filter()

“jim”

Page 30: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

filter(s -> s.length() < 4)

Stream<String>

Predicate<String

Stream<String>

filter()

Page 31: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

filter(s -> s.length() < 4)

Stream<String>

Predicate<String

Stream<String>

filter()

Page 32: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

filter(s -> s.length() < 4)

Stream<String>

Predicate<String

Stream<String>

filter()

“amy”

Page 33: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

filter(s -> s.length() < 4)

Stream<String>

Predicate<String

Stream<String>

filter()

Page 34: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

map()

map(Person::getCity)

Stream<Person> Stream<City>

Function<Person,City

Page 35: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

map()

map(Person::getCity)

Stream<Person> Stream<City>

Function<Person,City

bill

Page 36: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

map()

map(Person::getCity)

Stream<Person> Stream<City>

Function<Person,City

Page 37: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

map()

map(Person::getCity)

Stream<Person> Stream<City>

Function<Person,City

amy

Page 38: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

map()

map(Person::getCity)

Stream<Person> Stream<City>

Function<Person,City

Page 39: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

peek()

peek(System.out::println)

Consumer<T>

System.out::println

T

Stream<T>

Page 40: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

flatMapToInt()

Stream<String>

Function<String,IntStream>

IntStream

flatMapToInt(String::chars)

Page 41: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

flatMapToInt()

Stream<String>

Function<String,IntStream>

IntStream

'a' 'm' 'y'

flatMapToInt(String::chars)

Page 42: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

flatMapToInt()

Stream<String>

Function<String,IntStream>

IntStream

'm' 'y'

flatMapToInt(String::chars)

Page 43: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

flatMapToInt()

Stream<String>

Function<String,IntStream>

IntStream

'y'

flatMapToInt(String::chars)

Page 44: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

flatMapToInt()

Stream<String>

Function<String,IntStream>

IntStream

flatMapToInt(String::chars)

Page 45: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Ending Streams

Search findFirst(),findAny()anyMatch(), allMatch()

Side-effecting forEach(), forEachOrdered()

Reductions ...

Stream Sinks (terminal operations):

Page 46: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Parallelism

“The best way to write parallel applications is not to have to think about parallelism.”

Guy Steele

Page 47: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Automated Resource Management

Page 48: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Automated Resource Management

Page 49: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Assemblers

Automated Resource Management

Page 50: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

AssemblersLinkers

Automated Resource Management

Page 51: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

AssemblersLinkersRegister allocation

Automated Resource Management

Page 52: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

AssemblersLinkersRegister allocationHeap management

Automated Resource Management

Page 53: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

AssemblersLinkersRegister allocationHeap managementVirtual memory

Automated Resource Management

Page 54: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

AssemblersLinkersRegister allocationHeap managementVirtual memoryParallelisation

Automated Resource Management

Page 55: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Retooling

Page 56: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Some old habits won’t work any more

Retooling

Page 57: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Some old habits won’t work any moreminimising operation count (eg by reusing previously computed results)

Retooling

Page 58: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Some old habits won’t work any moreminimising operation count (eg by reusing previously computed results)

- be prepared to “waste” operations to reduce communication

Retooling

Page 59: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Some old habits won’t work any moreminimising operation count (eg by reusing previously computed results)

- be prepared to “waste” operations to reduce communication

minimising space usage (by sharing data between operations)

Retooling

Page 60: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Some old habits won’t work any moreminimising operation count (eg by reusing previously computed results)

- be prepared to “waste” operations to reduce communication

minimising space usage (by sharing data between operations)

- parallel programs trade space for reduced coupling

Retooling

Page 61: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Some old habits won’t work any moreminimising operation count (eg by reusing previously computed results)

- be prepared to “waste” operations to reduce communication

minimising space usage (by sharing data between operations)

- parallel programs trade space for reduced coupling

linear decomposition

Retooling

Page 62: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Some old habits won’t work any moreminimising operation count (eg by reusing previously computed results)

- be prepared to “waste” operations to reduce communication

minimising space usage (by sharing data between operations)

- parallel programs trade space for reduced coupling

linear decomposition

- processing one thing at a time to accumulate results

Retooling

Page 63: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Some old habits won’t work any moreminimising operation count (eg by reusing previously computed results)

- be prepared to “waste” operations to reduce communication

minimising space usage (by sharing data between operations)

- parallel programs trade space for reduced coupling

linear decomposition

- processing one thing at a time to accumulate results

Retooling

No more accumulators!

Page 64: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Seriously, No More Accumulators??

Page 65: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Seriously, No More Accumulators??

No more accumulators!

Page 66: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Seriously, No More Accumulators??

Divide And Conquer algorithms instead

- symmetric merge operations

No more accumulators!

Page 67: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Seriously, No More Accumulators??

Divide And Conquer algorithms instead

- symmetric merge operationsMajor impact on terminal operations

- almost all are accumulations of some kind

No more accumulators!

Page 68: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

• Using an accumulator:

Simple Example – Summation

int[] vals = new int[100];Arrays.setAll(vals, i -> i);

int sum = 0;for (int i = 0 ; i < vals.length ; i++) { sum += vals[i];}

0 1 2 3

+

+

+

Page 69: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

• Avoiding an accumulator:

Simple Example – Summation

Page 70: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

• Avoiding an accumulator:

Simple Example – Summation

Page 71: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

+

+

+

• Avoiding an accumulator:

Simple Example – Summation

int[] vals = new int[100];Arrays.setAll(vals, i -> i);

OptionalInt sum = Arrays.stream(vals) .reduce((a,b) -> a + b);

1 2 30

Page 72: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

+ +

+

• Avoiding an accumulator:

Simple Example – Summation

int[] vals = new int[100];Arrays.setAll(vals, i -> i);

OptionalInt sum = Arrays.stream(vals) .reduce((a,b) -> a + b);

1 2 30

Page 73: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

+ +

+

• Avoiding an accumulator:

Simple Example – Summation

int[] vals = new int[100];Arrays.setAll(vals, i -> i);

OptionalInt sum = Arrays.stream(vals) .reduce((a,b) -> a + b);

BinaryOperator must be associative!

1 2 30

Page 74: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

+ +

+

• Avoiding an accumulator:

Simple Example – Summation

int[] vals = new int[100];Arrays.setAll(vals, i -> i);

OptionalInt sum = Arrays.stream(vals) .reduce((a,b) -> a + b);

BinaryOperator must be associative!a + (b + c) = (a + b) + c

1 2 30

Page 75: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Reduction of Primitives0 1 2

+

+

+

+

+

+

+

3 4 5

0 0

Page 76: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Reduction of Primitives0 1 2

+

+

+

+

+

+

+

3 4 5

Identity

BinaryOperator

0 0

Page 77: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Reduction of Primitives0 1 2

+

+

+

+

+

+

+

3 4 5

Identity

BinaryOperator

0 0

Page 78: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Reduction of Mutable Objects?

add

add

add

add

add

add

combine

[ ] [ ]

Identity

Accumulator

Combiner

e0 e1 e2 e3 e4 e5

Page 79: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Reduction of Mutable Objects?

add

add

add

add

add

add

combine

[ ] [ ]

Identity

Accumulator

Combiner

e0 e1 e2 e3 e4 e5

Not�Parallel-ReadyNot�Parallel-Ready

Page 80: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Collector

combine

()->[]

Supplier

Accumulator

Combiner

e0 e1 e2 e3 e4 e5

()->[]

add

add

add

add

add

add

Page 81: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Using the Predefined Collectors

Predefined Standalone Collectors – from factory methods in Collectors class

• toList(), toSet(), toMap(), joining()

• toMap(), toCollection()

• groupingBy(), partitioningBy()

Page 82: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Using the Predefined Collectors

Predefined Standalone Collectors – from factory methods in Collectors class

• toList(), toSet(), toMap(), joining()

• toMap(), toCollection()

• groupingBy(), partitioningBy()

framework providesthe Supplier

Page 83: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Using the Predefined Collectors

Predefined Standalone Collectors – from factory methods in Collectors class

• toList(), toSet(), toMap(), joining()

• toMap(), toCollection()

• groupingBy(), partitioningBy()

user providesthe Supplier

framework providesthe Supplier

Page 84: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Using the Predefined Collectors

Predefined Standalone Collectors – from factory methods in Collectors class

• toList(), toSet(), toMap(), joining()

• toMap(), toCollection()

• groupingBy(), partitioningBy()

user providesthe Supplier

framework providesthe Supplier

produce a classification map

Page 85: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Simple Collector – toSet()people.stream().collect(Collectors.toSet())

Page 86: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Collector<Person,?,Set<Pers

Stream<Person> Set<Person>

Simple Collector – toSet()people.stream().collect(Collectors.toSet())

Page 87: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Collector<Person,?,Set<Pers

Stream<Person> Set<Person>bill

Simple Collector – toSet()people.stream().collect(Collectors.toSet())

Page 88: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Collector<Person,?,Set<Pers

Stream<Person> Set<Person>bill

Simple Collector – toSet()people.stream().collect(Collectors.toSet())

Page 89: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Collector<Person,?,Set<Pers

Stream<Person> Set<Person>bill

Simple Collector – toSet()people.stream().collect(Collectors.toSet())

Page 90: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Collector<Person,?,Set<Pers

Stream<Person> Set<Person>billjon

Simple Collector – toSet()people.stream().collect(Collectors.toSet())

Page 91: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Collector<Person,?,Set<Pers

Stream<Person> Set<Person>billjon

Simple Collector – toSet()people.stream().collect(Collectors.toSet())

Page 92: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Collector<Person,?,Set<Pers

Stream<Person> Set<Person>amy

billjon

Simple Collector – toSet()people.stream().collect(Collectors.toSet())

Page 93: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Collector<Person,?,Set<Pers

Stream<Person> Set<Person>

amy

billjon

Simple Collector – toSet()people.stream().collect(Collectors.toSet())

Page 94: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Collector<Person,?,Set<Pers

Set<Person>

amy

billjon

Simple Collector – toSet()people.stream().collect(Collectors.toSet())

Page 95: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Collector<Person,?,Set<Pers

Set<Person>{ , , }amybilljon

Simple Collector – toSet()people.stream().collect(Collectors.toSet())

Page 96: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

toMap(Function<T,K> keyMapper, Function<T,U> valueMapper)

people.stream().collect( Collectors.toMap(

Person::getCity, Person::getName))

Page 97: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

toMap(Function<T,K> keyMapper, Function<T,U> valueMapper)

Stream<Person>

toMap() Map<City,String>

Collector<Person,?,Map<City,String>

Page 98: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

toMap(Function<T,K> keyMapper, Function<T,U> valueMapper)

Stream<Person>

toMap() Map<City,String>

bill

Page 99: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

toMap(Function<T,K> keyMapper, Function<T,U> valueMapper)

Stream<Person>

toMap() Map<City,String>

bill

Person::getCity

Page 100: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

toMap(Function<T,K> keyMapper, Function<T,U> valueMapper)

Stream<Person>

toMap() Map<City,String>London

bill

Page 101: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

toMap(Function<T,K> keyMapper, Function<T,U> valueMapper)

Stream<Person>

toMap() Map<City,String>London

bill Person::getName

Page 102: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

toMap(Function<T,K> keyMapper, Function<T,U> valueMapper)

Stream<Person>

toMap() Map<City,String>London “Bill”

bill Person::getName

Page 103: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

toMap(Function<T,K> keyMapper, Function<T,U> valueMapper)

Stream<Person>

toMap() Map<City,String>London “Bill”

Page 104: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

toMap(Function<T,K> keyMapper, Function<T,U> valueMapper)

Stream<Person>

toMap() Map<City,String>

amy

London “Bill”

Page 105: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

toMap(Function<T,K> keyMapper, Function<T,U> valueMapper)

Stream<Person>

toMap() Map<City,String>

Athensamy

London “Bill”

Page 106: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

toMap(Function<T,K> keyMapper, Function<T,U> valueMapper)

Stream<Person>

toMap() Map<City,String>

“Amy”Athens

London “Bill”

Page 107: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

toMap(Function<T,K> keyMapper, Function<T,U> valueMapper)

Stream<Person>

toMap() Map<City,String>

“Amy”Athensjon

London “Bill”

Page 108: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

toMap(Function<T,K> keyMapper, Function<T,U> valueMapper)

Stream<Person>

toMap() Map<City,String>

“Amy”Athens

London “Bill”

Tulsa “Jon”

Page 109: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

toMap(Function<T,K> keyMapper, Function<T,U> valueMapper)

toMap() Map<City,String>

“Amy”Athens

London “Bill”

Tulsa “Jon”

Page 110: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

toMap(Function<T,K> keyMapper, Function<T,U> valueMapper)

toMap() Map<City,String>

“Amy”AthensLondon “Bill”

Tulsa “Jon”

Page 111: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

groupingBy(Function<T,K> classifier)Uses the classifier function to make a classification mapping

Like toMap(), except that the values placed in the map are lists of the elements, one List corresponding to each classification key:

For example, use Person.getCity() to make a Map<City,List<Person>>

Map<City,List<Person>> peopleByCity = people.stream(). collect(Collectors.groupingBy(Person::getCity));

Page 112: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Stream<Person>

groupingBy() Map<City,List<Person>>

bill

jon

amy Athens

London

Collector<Person,?,Map<City,List<Person>>>

groupingBy(Function<Person,City>)

Classifier

Person→City

Page 113: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Stream<Person>

groupingBy() Map<City,List<Person>>

bill

jon

amy Athens

London

groupingBy(Function<Person,City>)

Page 114: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Stream<Person>

groupingBy() Map<City,List<Person>>

bill

jon

amy Athens

bill London

groupingBy(Function<Person,City>)

Page 115: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Stream<Person>

groupingBy() Map<City,List<Person>>

bill

jon

amy Athens

billLondon

groupingBy(Function<Person,City>)

[ ]

Page 116: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Stream<Person>

groupingBy() Map<City,List<Person>>

bill

jon

amy Athens [ ]

bill

amy

London

groupingBy(Function<Person,City>)

[ ]

Page 117: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Stream<Person>

groupingBy() Map<City,List<Person>>

bill

jon

amy Athens [ ]

[ , ]bill

amy

jonLondon

groupingBy(Function<Person,City>)

Page 118: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

groupingBy() Map<City,List<Person>>

bill

jon

amy Athens [ ]

[ , ]bill

amy

jonLondon

groupingBy(Function<Person,City>)

Page 119: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

groupingBy() Map<City,List<Person>>

bill

jon

amy

Athens [ ]

[ , ]bill

amy

jonLondon

groupingBy(Function<Person,City>)

Page 120: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

groupingBy(classifier, downstream)

Map<City,List<Person>> peopleByCity = people.stream(). collect(Collectors.groupingBy(Person::getCity,toSet()));

Uses the classifier function to make a classification mapping into a container defined by a downstream Collector

Like toMap(), except that the values placed in the map are containers of the elements, one container corresponding to each classification key:

For example, use Person.getCity() to make a Map<City,Set<Person>>

Map<City,Set<Person>> peopleByCity = people.stream(). collect(Collectors.groupingBy(Person::getCity,toSet()));

Page 121: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

groupingBy(Function classifier,Collector downstream))

Stream<Person>

groupingBy()Map<City,Set<Person>>

bill

jon

amy

London

Athens

DownstreamCollector

—toSet()

Stream<Person>

Classifier

Person→City

Page 122: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

groupingBy(Function classifier,Collector downstream))

Stream<Person>

groupingBy()Map<City,Set<Person>>

bill

jon

amy

London

Athens

Page 123: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

groupingBy(Function classifier,Collector downstream))

Stream<Person>

groupingBy()Map<City,Set<Person>>

bill

jon

amy

London

Athens

bill

Page 124: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

groupingBy(Function classifier,Collector downstream))

Stream<Person>

groupingBy()Map<City,Set<Person>>

bill

jon

amy

London

Athens

bill

Page 125: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

groupingBy(Function classifier,Collector downstream))

Stream<Person>

groupingBy()Map<City,Set<Person>>

bill

jon

amy

London

Athens

bill

Page 126: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

groupingBy(Function classifier,Collector downstream))

Stream<Person>

groupingBy()Map<City,Set<Person>>

bill

jon

amy

London

Athensamy

bill

Page 127: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

groupingBy(Function classifier,Collector downstream))

Stream<Person>

groupingBy()Map<City,Set<Person>>

bill

jon

amy

London

Athens amy

bill

Page 128: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

groupingBy(Function classifier,Collector downstream))

Stream<Person>

groupingBy()Map<City,Set<Person>>

bill

jon

amy

London

Athens amy

bill

Page 129: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

groupingBy(Function classifier,Collector downstream))

Stream<Person>

groupingBy()Map<City,Set<Person>>

bill

jon

amy

London

Athens amy

jon bill

Page 130: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

groupingBy(Function classifier,Collector downstream))

Stream<Person>

groupingBy()Map<City,Set<Person>>

bill

jon

amy

London

Athens amy

jonbill

Page 131: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

groupingBy(Function classifier,Collector downstream))

groupingBy()Map<City,Set<Person>>

bill

jon

amy

London

Athens amy

jonbill

Page 132: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

groupingBy(Function classifier,Collector downstream))

groupingBy()Map<City,Set<Person>>

bill

jon

amy

London

Athens amy

jonbill

Page 133: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

groupingBy(Function classifier,Collector downstream))

groupingBy()Map<City,Set<Person>>

bill

jon

amy

London

Athens { }amy

{ , }jonbill

Page 134: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

groupingBy(Function classifier,Collector downstream))

groupingBy()Map<City,Set<Person>>

bill

jon

amy

London

Athens { }amy

{ , }jonbill

Page 135: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Specialised Downstream Collectors

Stream<Person>

groupingBy()

bill

jon

amy

London

Athens

amyjonbillDownstream

CollectorClassifier

Duals of convenience reductionsMapping collector

“Ordinary”collectors +

Page 136: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Concurrent Collection

Page 137: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Concurrent Collection

Page 138: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Concurrent CollectionThread safety is guaranteed by the framework

• Even for non-threadsafe containers!

Page 139: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Concurrent CollectionThread safety is guaranteed by the framework

• Even for non-threadsafe containers!

But at a price... So what if your container is already threadsafe?

• a concurrentMap implementation?

Page 140: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Concurrent CollectionThread safety is guaranteed by the framework

• Even for non-threadsafe containers!

But at a price... So what if your container is already threadsafe?

• a concurrentMap implementation?

Page 141: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Concurrent CollectionThread safety is guaranteed by the framework

• Even for non-threadsafe containers!

But at a price... So what if your container is already threadsafe?

• a concurrentMap implementation?

Every overload of toMap() and groupingBy() has a dual

• toConcurrentMap(...)

• groupingByConcurrent(...)

Page 142: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Writing a Collector

Page 143: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Writing a Collector

Why would you want to?

Page 144: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Writing a Collector

Why would you want to?

• accumulate to a container that doesn’t implement Collection

Page 145: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Writing a Collector

Why would you want to?

• accumulate to a container that doesn’t implement Collection

• share state between values being collected

Page 146: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Writing a Collector

Why would you want to?

• accumulate to a container that doesn’t implement Collection

• share state between values being collected

• to show how to parallelize “iterative-looking” problems

Page 147: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Oprah’s Problem

Page 148: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Oprah’s Problem

How to find a book?

Page 149: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Oprah’s Problem

How to find a book?

336640

144624

Page count 239640

3841104

172400

Page 150: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

What Oprah Needs

New Earth 0Poisonwood Bible 336

Night 976A Fine Balance 1120

...

Cumulative page counts

Page 151: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Creating A Partial Solution

,“Night” 144 976 “AFB” 624 1120 ]“NE” 336 0 “PB” 640 336[ , ,

Page 152: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Creating A Partial Solution

,“Night” 144 0[ “AFB” 624 144 ]“NE” 336 0 “PB” 640 336[ ],

,“Night” 144 976 “AFB” 624 1120 ]“NE” 336 0 “PB” 640 336[ , ,

Page 153: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Creating A Partial Solution

combiner

,“Night” 144 0[ “AFB” 624 144 ]“NE” 336 0 “PB” 640 336[ ],

,“Night” 144 976 “AFB” 624 1120 ]“NE” 336 0 “PB” 640 336[ , ,

Page 154: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Creating A Partial Solution

combiner

,“Night” 144 0[ “AFB” 624 144 ]“NE” 336 0 “PB” 640 336[ ],

,“Night” 144 976 “AFB” 624 1120 ]“NE” 336 0 “PB” 640 336[ , ,

Page 155: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Supplier and Accumulator

“NE” 336 0 “PB” 640 336[ ],

]“NE” 336 0[

][

aNewEarth thePoisonwoodBible

accumulator

accumulator

supplier

Page 156: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Combiner

,“Night” 144 976 “AFB” 624 1120 ]“NE” 336 0 “PB” 640 336[ , ,

Page 157: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Combiner

,“Night” 144 0[ “AFB” 624 144 ]“NE” 336 0 “PB” 640 336[ ],

,“Night” 144 976 “AFB” 624 1120 ]“NE” 336 0 “PB” 640 336[ , ,

Page 158: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Combiner

combiner

,“Night” 144 0[ “AFB” 624 144 ]“NE” 336 0 “PB” 640 336[ ],

,“Night” 144 976 “AFB” 624 1120 ]“NE” 336 0 “PB” 640 336[ , ,

Page 159: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Combiner

combiner

,“Night” 144 0[ “AFB” 624 144 ]“NE” 336 0 “PB” 640 336[ ],

,“Night” 144 976 “AFB” 624 1120 ]“NE” 336 0 “PB” 640 336[ , ,

976

Page 160: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Combiner

combiner

,“Night” 144 0[ “AFB” 624 144 ]“NE” 336 0 “PB” 640 336[ ],

,“Night” 144 976 “AFB” 624 1120 ]“NE” 336 0 “PB” 640 336[ , ,

976

Page 161: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Combiner

combiner

,“Night” 144 0[ “AFB” 624 144 ]“NE” 336 0 “PB” 640 336[ ],

,“Night” 144 976 “AFB” 624 1120 ]“NE” 336 0 “PB” 640 336[ , ,

976

Page 162: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Sources – parallel streams

Implemented by a Spliterator

Page 163: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Sources – parallel streams

Implemented by a Spliterator

Page 164: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Sources – parallel streams

Implemented by a Spliterator

Page 165: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Sources – parallel streams

Implemented by a Spliterator

Page 166: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Sources – parallel streams

Implemented by a Spliterator

Page 167: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Sources – parallel streams

Implemented by a Spliterator

Page 168: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Sources – parallel streams

Implemented by a Spliterator

Page 169: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Sources – parallel streams

Implemented by a Spliterator

Page 170: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Sources – parallel streams

Implemented by a Spliterator

Page 171: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

x2

x0

x1

x3

x0

x1

x2

x3

Intermediate Op(s)

(Mutable)Reduction

Spliterator

Visualizing Stream Operations

Page 172: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

x2

x0

x1

x3

x0

x1

x2x3

Intermediate Op(s)

(Mutable)Reduction

Spliterator

Visualizing Stream Operations

Page 173: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

x2

x0

x1

x3

y0

y1

y2

y3

Intermediate Op(s)

(Mutable)Reduction

Spliterator

Visualizing Stream Operations

Page 174: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

x2

x0

x1

x3

y0y1y2y3

Intermediate Op(s)

(Mutable)Reduction

Spliterator

Visualizing Stream Operations

Page 175: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

x2

x0

x1

x3

x0

x1

x2

x3

Visualizing Stream Operations

Intermediate Op(s)

(Mutable)Reduction

Spliterator

Page 176: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

x2

x0

x1

x3

x0

x1

x2

x3

Visualizing Stream Operations

Intermediate Op(s)

(Mutable)Reduction

Spliterator

Page 177: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

x2

x0

x1

x3

x0

x1

x2x3

Visualizing Stream Operations

Intermediate Op(s)

(Mutable)Reduction

Spliterator

Page 178: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

x2

x0

x1

x3

x0

x1

x2x3

Visualizing Stream Operations

Intermediate Op(s)

(Mutable)Reduction

Spliterator

Page 179: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

x2

x0

x1

x3

x0

x1

x2x3

Visualizing Stream Operations

Intermediate Op(s)

(Mutable)Reduction

Spliterator

Page 180: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

x2

x0

x1

x3

Visualizing Stream Operations

y0

y1

y2

y3

Intermediate Op(s)

(Mutable)Reduction

Spliterator

Page 181: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

x2

x0

x1

x3

Visualizing Stream Operations

y0y1y2y3

Intermediate Op(s)

(Mutable)Reduction

Spliterator

Page 182: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Visualizing Stream Operations

x2

x1

x3

x1

x2

x3

Intermediate Op(s)

(Mutable)Reduction

Spliterator

x0x0

peek(System.out::print)

Page 183: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Visualizing Stream Operations

x2

x1

x3

x1

x2

x3

Intermediate Op(s)

(Mutable)Reduction

Spliterator

x0x0

peek(System.out::print)

Page 184: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Visualizing Stream Operations

x2

x1

x3

x1

x2

x3

Intermediate Op(s)

(Mutable)Reduction

Spliterator

x0

x0

x0

peek(System.out::print)

Page 185: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Visualizing Stream Operations

x2

x1

x3

x1

x2

x3

Intermediate Op(s)

(Mutable)Reduction

Spliterator

x0

x0

x0

peek(System.out::print)

Page 186: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Visualizing Stream Operations

x2

x1

x3

x1

x2x3

Intermediate Op(s)

(Mutable)Reduction

Spliterator

x0

x2

x0

x0

peek(System.out::print)

Page 187: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Visualizing Stream Operations

x2

x1

x3

x1

x2x3

Intermediate Op(s)

(Mutable)Reduction

Spliterator

x0x2

x0

x0

peek(System.out::print)

Page 188: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Visualizing Stream Operations

x2

x1

x3

x1

x2x3

Intermediate Op(s)

(Mutable)Reduction

Spliterator

x0x2

x0

x0

peek(System.out::print)

Page 189: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Visualizing Stream Operations

x2

x1

x3

x1

x2x3

Intermediate Op(s)

(Mutable)Reduction

Spliterator

x0x2

x0

x3

x0

peek(System.out::print)

Page 190: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Visualizing Stream Operations

x2

x1

x3

x1

x2x3

Intermediate Op(s)

(Mutable)Reduction

Spliterator

x0x2

x0

x3

x0

peek(System.out::print)

Page 191: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Visualizing Stream Operations

x2

x1

x3

x1

x2x3

Intermediate Op(s)

(Mutable)Reduction

Spliterator

x0x2

x0

x3

x0

peek(System.out::print)

Page 192: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Visualizing Stream Operations

x2

x1

x3

x1

x2x3

Intermediate Op(s)

(Mutable)Reduction

Spliterator

x0x2

x0

x3

x0

peek(System.out::print)

Page 193: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Visualizing Stream Operations

x2

x1

x3

y0

y1

y2

y3

Intermediate Op(s)

(Mutable)Reduction

Spliterator

x0x2

x0

x3peek(System.out::print)

Page 194: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Visualizing Stream Operations

x2

x1

x3

y0y1y2y3

Intermediate Op(s)

(Mutable)Reduction

Spliterator

x0x2

x0

x3peek(System.out::print)

Page 195: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

Visualizing Stream Operations

x2

x1

x3

Intermediate Op(s)

(Mutable)Reduction

Spliterator

x0x2

x0

x3peek(System.out::print)

Page 196: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

What Does Parallel-Ready Mean?

Page 197: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

What Does Parallel-Ready Mean?

– sequential execution is no longer the default

Page 198: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

What Does Parallel-Ready Mean?

– sequential execution is no longer the default– it’s still often more efficient, but that will change

Page 199: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

What Does Parallel-Ready Mean?

– sequential execution is no longer the default– it’s still often more efficient, but that will change– code must be agnostic about its execution mode

Page 200: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

What Does Parallel-Ready Mean?

– sequential execution is no longer the default– it’s still often more efficient, but that will change– code must be agnostic about its execution mode– operations in the Stream API have equivalent effect

Page 201: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

What Does Parallel-Ready Mean?

– sequential execution is no longer the default– it’s still often more efficient, but that will change– code must be agnostic about its execution mode– operations in the Stream API have equivalent effect- sequential or parallel

Page 202: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

What Does Parallel-Ready Mean?

– sequential execution is no longer the default– it’s still often more efficient, but that will change– code must be agnostic about its execution mode– operations in the Stream API have equivalent effect- sequential or parallel

- may be equally non-deterministic

Page 203: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

What Does Parallel-Ready Mean?

– sequential execution is no longer the default– it’s still often more efficient, but that will change– code must be agnostic about its execution mode– operations in the Stream API have equivalent effect- sequential or parallel

- may be equally non-deterministic

– decouples execution mode from functional behavior

Page 204: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

What Does Parallel-Ready Mean?

– sequential execution is no longer the default– it’s still often more efficient, but that will change– code must be agnostic about its execution mode– operations in the Stream API have equivalent effect- sequential or parallel

- may be equally non-deterministic

– decouples execution mode from functional behavior– parallel-ready is not only about parallel execution!

Page 205: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

What Does Parallel-Ready Mean?

– sequential execution is no longer the default– it’s still often more efficient, but that will change– code must be agnostic about its execution mode– operations in the Stream API have equivalent effect- sequential or parallel

- may be equally non-deterministic

– decouples execution mode from functional behavior– parallel-ready is not only about parallel execution!- or even mainly, for now

Page 206: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

So, Is Your Code Parallel-Ready?

Most unlikely. But it can be!

The Stream API provides a framework and a lot of support for writing PR code. You just need to co-operate with it.

- it depends on you behaving sanely

Page 207: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Using Streams Sanely

Rules in the JavaDoc for java.util.stream Stateless behavior:- avoid stateful behavioral parameters

- “one whose result depends on any state which might change during the execution of the stream pipeline”

...

Page 208: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Using Streams Sanely

Rules in the JavaDoc for java.util.stream Stateless behavior:- avoid stateful behavioral parameters

- “one whose result depends on any state which might change during the execution of the stream pipeline”

...

Safely

Page 209: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Using Streams Sanely

Rules in the JavaDoc for java.util.stream ...Non-interference- don’t modify a stream’s data source during execution

- you may if it’s a thread-safe class

Don’t rely on side-effects- use for debugging only

Page 210: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Using Streams Sanely

Rules in the JavaDoc for java.util.stream ...Non-interference- don’t modify a stream’s data source during execution

- you may if it’s a thread-safe class

Don’t rely on side-effects- use for debugging only

Safely

Page 211: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Conclusion

The Streams API offers a framework for- programming bulk data operations in parallel-ready style

- easy parallellism, with thread-safe access to non-threadsafe containers

All we have to do is co-operate with it!Parallel-Ready code starts today!

Page 212: Parallel-Ready Java Code: Managing Mutation in an Imperative Language

#parallelready @mauricenaftalin

Resources

www.lambdafaq.orgwww.masteringlambdas.org