82

JDK8: Stream style

Embed Size (px)

DESCRIPTION

JDK8 is bringing lambdas into the Java world. But without significant Java SE 8 libraries extensions lambdas would be only a toy. The centerpiece of the new libraries is the Streams API (formerly ‘Collections bulk operations’). This session presents the Streams API and examples how to get the best performance and scalability using the library.

Citation preview

Page 1: JDK8: Stream style

Java8: Stream Style

Sergey Kuksenko

[email protected], @kuksenk0

Page 2: JDK8: Stream style

The following is intended to outline our general product direction. Itis intended for information purposes only, and may not beincorporated into any contract. It is not a commitment to deliver anymaterial, code, or functionality, and should not be relied upon inmaking purchasing decisions. The development, release, and timingof any features or functionality described for Oracle’s productsremains at the sole discretion of Oracle.

Slide 2/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 3: JDK8: Stream style

Motivation

Slide 3/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 4: JDK8: Stream style

Motivation

Everything is well. Why do we need any Streams?

public void printGroups(List <People > people) {

Set <Group > groups = new HashSet <>();

for (People p : people) {

if (p.getAge () >= 65)

groups.add(p.getGroup ());

}

List <Group > sorted = new ArrayList <>(groups );

Collections.sort(sorted , new Comparator <Group >() {

public int compare(Group a, Group b) {

return Integer.compare(a.getSize(), b.getSize ())

}

});

for (Group g : sorted)

System.out.println(g.getName ());

}

Slide 4/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 5: JDK8: Stream style

Motivation

Everything is well. Why do we need any Streams?

public void printGroups(List <People > people) {

Set <Group > groups = new HashSet <>();

for (People p : people) {

if (p.getAge () >= 65)

groups.add(p.getGroup ());

}

List <Group > sorted = new ArrayList <>(groups );

Collections.sort(sorted , new Comparator <Group >() {

public int compare(Group a, Group b) {

return Integer.compare(a.getSize(), b.getSize ())

}

});

for (Group g : sorted)

System.out.println(g.getName ());

}

Slide 4/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 6: JDK8: Stream style

Motivation

It would be awesome to omit miles and miles of duplicated code.

public void printGroups(List <People > people) {

people.stream ()

.filter(p -> p.getAge () > 65)

.map(p -> p.getGroup ())

.distinct ()

.sorted(comparing(g -> g.getSize ()))

.map(g -> g.getName ())

.forEach(n -> System.out.println(n));

}

Slide 5/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 7: JDK8: Stream style

Motivation

It would be awesome to do less work, and do it later (laziness).

public void printGroups(List <People > people) {

people.stream ()

.filter(p -> p.getAge () > 65)

.map(p -> p.getGroup ())

.distinct ()

.sorted(comparing(g -> g.getSize ()))

.map(g -> g.getName ())

.forEach(n -> System.out.println(n));//⇐ ACTIONS!

}

Slide 6/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 8: JDK8: Stream style

Motivation

Parallelism?

Collection <Item > data;

...

for(int i=0; i < data.size (); i++) {

processItem(data.get(i));

}

Slide 7/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 9: JDK8: Stream style

Motivation

Parallelism?

Collection <Item > data;

...

for(Item item : data) {

processItem(item);

}

Slide 8/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 10: JDK8: Stream style

Motivation

Parallelism?

Collection <Item > data;

...

#pragma omg parallel

for(Item item : data) {

processItem(item);

}

Slide 9/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 11: JDK8: Stream style

Motivation

Parallelism?

Collection <Item > data;

...

#pragma omp parallel

for(Item item : data) {

processItem(item);

}

Slide 10/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 12: JDK8: Stream style

Motivation

Parallelism?

Collection <Item > data;

...

parallel_for(Item item : data) {

processItem(item);

}

Slide 11/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 13: JDK8: Stream style

Motivation

Parallelism!

Collection <Item > data;

...

data.parallelStream ()

.forEach(item -> processItem(item ));

}

Slide 12/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 14: JDK8: Stream style

Design

Slide 13/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 15: JDK8: Stream style

Design

Most of the code fits the same simple pattern

𝑠𝑜𝑢𝑟𝑐𝑒

→ 𝑜𝑝 → 𝑜𝑝 → 𝑜𝑝 →

“sources”: collections, iterators, channels, ...

“operations”: filter, map, reduce, ...

“sinks”: collections, locals, ...

Slide 14/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 16: JDK8: Stream style

Design

Most of the code fits the same simple pattern

𝑠𝑜𝑢𝑟𝑐𝑒 → 𝑜𝑝

→ 𝑜𝑝 → 𝑜𝑝 →

“sources”: collections, iterators, channels, ...

“operations”: filter, map, reduce, ...

“sinks”: collections, locals, ...

Slide 14/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 17: JDK8: Stream style

Design

Most of the code fits the same simple pattern

𝑠𝑜𝑢𝑟𝑐𝑒 → 𝑜𝑝 → 𝑜𝑝

→ 𝑜𝑝 →

“sources”: collections, iterators, channels, ...

“operations”: filter, map, reduce, ...

“sinks”: collections, locals, ...

Slide 14/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 18: JDK8: Stream style

Design

Most of the code fits the same simple pattern

𝑠𝑜𝑢𝑟𝑐𝑒 → 𝑜𝑝 → 𝑜𝑝 → 𝑜𝑝

“sources”: collections, iterators, channels, ...

“operations”: filter, map, reduce, ...

“sinks”: collections, locals, ...

Slide 14/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 19: JDK8: Stream style

Design

Most of the code fits the same simple pattern

𝑠𝑜𝑢𝑟𝑐𝑒 → 𝑜𝑝 → 𝑜𝑝 → 𝑜𝑝 →

“sources”: collections, iterators, channels, ...

“operations”: filter, map, reduce, ...

“sinks”: collections, locals, ...

Slide 14/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 20: JDK8: Stream style

Design

Most of the code fits the same simple pattern

𝑠𝑜𝑢𝑟𝑐𝑒 → 𝑜𝑝 → 𝑜𝑝 → 𝑜𝑝 → 𝑔𝑎𝑛𝑔𝑛𝑎𝑚𝑠𝑡𝑦𝑙𝑒

“sources”: collections, iterators, channels, ...

“operations”: filter, map, reduce, ...

“sinks”: collections, locals, ...

Slide 14/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 21: JDK8: Stream style

Design

Most of the code fits the same simple pattern

𝑠𝑜𝑢𝑟𝑐𝑒 → 𝑜𝑝 → 𝑜𝑝 → 𝑜𝑝 → 𝑠𝑖𝑛𝑘

“sources”: collections, iterators, channels, ...

“operations”: filter, map, reduce, ...

“sinks”: collections, locals, ...

Slide 14/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 22: JDK8: Stream style

Design

Most of the code fits the same simple pattern

𝑠𝑜𝑢𝑟𝑐𝑒 → 𝑜𝑝 → 𝑜𝑝 → 𝑜𝑝 → 𝑠𝑖𝑛𝑘

“sources”: collections, iterators, channels, ...

“operations”: filter, map, reduce, ...

“sinks”: collections, locals, ...

Slide 14/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 23: JDK8: Stream style

Sources

Standard classes?not-yet-created classes?3𝑟𝑑 party classes?

Collection?should we put everything into collection?

Iterable?“Iterator Hell” (inherently sequential)interface pollution

Stream!new (just invented) interface with required semanticinject the only stream() method into existing classes

Slide 15/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 24: JDK8: Stream style

Sources

Standard classes?not-yet-created classes?3𝑟𝑑 party classes?

Collection?should we put everything into collection?

Iterable?“Iterator Hell” (inherently sequential)interface pollution

Stream!new (just invented) interface with required semanticinject the only stream() method into existing classes

Slide 15/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 25: JDK8: Stream style

Sources

Standard classes?not-yet-created classes?3𝑟𝑑 party classes?

Collection?should we put everything into collection?

Iterable?“Iterator Hell” (inherently sequential)interface pollution

Stream!new (just invented) interface with required semanticinject the only stream() method into existing classes

Slide 15/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 26: JDK8: Stream style

Sources

Standard classes?not-yet-created classes?3𝑟𝑑 party classes?

Collection?should we put everything into collection?

Iterable?“Iterator Hell” (inherently sequential)interface pollution

Stream!new (just invented) interface with required semanticinject the only stream() method into existing classes

Slide 15/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 27: JDK8: Stream style

Stream

Slide 16/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 28: JDK8: Stream style

Stream

“A multiplicity of values”

Not a collection (no storage)

Operations are deferred as long as possible

May be infinite

Source is unmodifiable

Can be used only once

Ordered/Unordered

Parallel/Sequential

Primitive specializations:IntStream, LongStream, DoubleStream

Slide 17/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 29: JDK8: Stream style

Stream pipeline

𝑎 𝑠𝑜𝑢𝑟𝑐𝑒: Source → Stream

𝑖𝑛𝑡𝑒𝑟𝑚𝑒𝑑𝑖𝑎𝑡𝑒 𝑜𝑝𝑒𝑟𝑎𝑡𝑖𝑜𝑛𝑠: Stream → Stream

𝑎 𝑡𝑒𝑟𝑚𝑖𝑛𝑎𝑙 𝑜𝑝𝑒𝑟𝑎𝑡𝑖𝑜𝑛: Stream → PROFIT!

public void printGroups(List <People > people) {

people.stream()

.filter(p -> p.getAge () > 65)

.map(p -> p.getGroup ())

.distinct()

.sorted(comparing(g -> g.getSize ()))

.map(g -> g.getName ())

.forEach(n -> System.out.println(n));

}

Slide 18/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 30: JDK8: Stream style

Stream pipeline

𝑎 𝑠𝑜𝑢𝑟𝑐𝑒: Source → Stream

𝑖𝑛𝑡𝑒𝑟𝑚𝑒𝑑𝑖𝑎𝑡𝑒 𝑜𝑝𝑒𝑟𝑎𝑡𝑖𝑜𝑛𝑠: Stream → Stream

𝑎 𝑡𝑒𝑟𝑚𝑖𝑛𝑎𝑙 𝑜𝑝𝑒𝑟𝑎𝑡𝑖𝑜𝑛: Stream → PROFIT!

public void printGroups(List <People > people) {

people.stream()

.filter(p -> p.getAge () > 65)

.map(p -> p.getGroup ())

.distinct()

.sorted(comparing(g -> g.getSize ()))

.map(g -> g.getName ())

.forEach(n -> System.out.println(n));

}

Slide 18/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 31: JDK8: Stream style

Stream pipeline

𝑎 𝑠𝑜𝑢𝑟𝑐𝑒: Source → Stream

𝑖𝑛𝑡𝑒𝑟𝑚𝑒𝑑𝑖𝑎𝑡𝑒 𝑜𝑝𝑒𝑟𝑎𝑡𝑖𝑜𝑛𝑠: Stream → Stream

𝑎 𝑡𝑒𝑟𝑚𝑖𝑛𝑎𝑙 𝑜𝑝𝑒𝑟𝑎𝑡𝑖𝑜𝑛: Stream → PROFIT!

public void printGroups(List <People > people) {

people.stream()

.filter(p -> p.getAge () > 65)

.map(p -> p.getGroup ())

.distinct()

.sorted(comparing(g -> g.getSize ()))

.map(g -> g.getName ())

.forEach(n -> System.out.println(n));

}

Slide 18/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 32: JDK8: Stream style

Stream pipeline

𝑎 𝑠𝑜𝑢𝑟𝑐𝑒: Source → Stream

𝑖𝑛𝑡𝑒𝑟𝑚𝑒𝑑𝑖𝑎𝑡𝑒 𝑜𝑝𝑒𝑟𝑎𝑡𝑖𝑜𝑛𝑠: Stream → Stream

𝑎 𝑡𝑒𝑟𝑚𝑖𝑛𝑎𝑙 𝑜𝑝𝑒𝑟𝑎𝑡𝑖𝑜𝑛: Stream → PROFIT!

public void printGroups(List <People > people) {

Stream <People > s1 = people.stream ();

Stream <People > s2 = s1.filter(p -> p.getAge () > 65);

Stream <Group > s3 = s2.map(p -> p.getGroup ());

Stream <Group > s4 = s3.distinct ();

Stream <Group > s5 = s4.sorted(comparing(g->g.getSize ()));

Stream <String > s6 = s5.map(g -> g.getName ());

s6.forEach(n -> System.out.println(n));

}

Slide 19/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 33: JDK8: Stream style

Stream Sources

Slide 20/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 34: JDK8: Stream style

Stream Sources: collections

ArrayList <T> list;

Stream <T> s = list.stream (); // sized , ordered

HashSet <T> set;

Stream <T> s = set.stream (); // sized , distinct

TreeSet <T> set;

Stream <T> s = set.stream (); // sized , distinct

// sorted , ordered

Slide 21/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 35: JDK8: Stream style

Stream Sources: collections

ArrayList <T> list;

Stream <T> s = list.stream (); // sized , ordered

HashSet <T> set;

Stream <T> s = set.stream (); // sized , distinct

TreeSet <T> set;

Stream <T> s = set.stream (); // sized , distinct

// sorted , ordered

Slide 21/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 36: JDK8: Stream style

Stream Sources: collections

ArrayList <T> list;

Stream <T> s = list.stream (); // sized , ordered

HashSet <T> set;

Stream <T> s = set.stream (); // sized , distinct

TreeSet <T> set;

Stream <T> s = set.stream (); // sized , distinct

// sorted , ordered

Slide 21/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 37: JDK8: Stream style

Stream Sources: factories, builders

T[] arr;

Stream <T> s = Arrays.stream(arr);

Stream <T> s = Stream.of(v0, v1, v2);

Stream <T> s = Stream.builder ()

.add(v0).add(v1).add(v2)

.build ();

IntStream s = IntStream.range(0, 100);

Slide 22/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 38: JDK8: Stream style

Stream Sources: factories, builders

T[] arr;

Stream <T> s = Arrays.stream(arr);

Stream <T> s = Stream.of(v0, v1, v2);

Stream <T> s = Stream.builder ()

.add(v0).add(v1).add(v2)

.build ();

IntStream s = IntStream.range(0, 100);

Slide 22/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 39: JDK8: Stream style

Stream Sources: factories, builders

T[] arr;

Stream <T> s = Arrays.stream(arr);

Stream <T> s = Stream.of(v0, v1, v2);

Stream <T> s = Stream.builder ()

.add(v0).add(v1).add(v2)

.build ();

IntStream s = IntStream.range(0, 100);

Slide 22/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 40: JDK8: Stream style

Stream Sources: factories, builders

T[] arr;

Stream <T> s = Arrays.stream(arr);

Stream <T> s = Stream.of(v0, v1, v2);

Stream <T> s = Stream.builder ()

.add(v0).add(v1).add(v2)

.build ();

IntStream s = IntStream.range(0, 100);

Slide 22/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 41: JDK8: Stream style

Stream Sources: generators

AtomicInteger init = new AtomicInteger (0);

Stream <Integer > s =

Stream.generate(init:: getAndIncrement );

Stream <Integer > s = Stream.iterate(0, i -> i+1);

Slide 23/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 42: JDK8: Stream style

Stream Sources: generators

AtomicInteger init = new AtomicInteger (0);

Stream <Integer > s =

Stream.generate(init:: getAndIncrement );

Stream <Integer > s = Stream.iterate(0, i -> i+1);

Slide 23/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 43: JDK8: Stream style

Stream Sources: others

Stream <String > s = bufferedReader.lines ();

Stream <String > s = Pattern.compile(myRegEx)

.splitAsStream(myStr);

DoubleStream s =

new SplittableRandom (). doubles ();

Slide 24/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 44: JDK8: Stream style

Stream Sources: others

Stream <String > s = bufferedReader.lines ();

Stream <String > s = Pattern.compile(myRegEx)

.splitAsStream(myStr);

DoubleStream s =

new SplittableRandom (). doubles ();

Slide 24/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 45: JDK8: Stream style

Stream Sources: others

Stream <String > s = bufferedReader.lines ();

Stream <String > s = Pattern.compile(myRegEx)

.splitAsStream(myStr);

DoubleStream s =

new SplittableRandom (). doubles ();

Slide 24/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 46: JDK8: Stream style

Intermediate Operations

Slide 25/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 47: JDK8: Stream style

Intermediate Operations

Stream <S> s;

Stream <S> s.filter(Predicate <S>);

Stream <T> s.map(Function <S, T>);

Stream <T> s.flatMap(Function <S, Stream <T>>);

Stream <S> s.peek(Consumer <S>);

Stream <S> s.sorted ();

Stream <S> s.distinct ();

Stream <S> s.limit(long);

Stream <S> s.skip(long);

Stream <S> s.unordered ();

Stream <S> s.parallel ();

Stream <S> s.sequential ();

Slide 26/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 48: JDK8: Stream style

Intermediate Operations

Stream <S> s;

Stream <S> s.filter(Predicate <S>);

Stream <T> s.map(Function <S, T>);

Stream <T> s.flatMap(Function <S, Stream <T>>);

Stream <S> s.peek(Consumer <S>);

Stream <S> s.sorted ();

Stream <S> s.distinct ();

Stream <S> s.limit(long);

Stream <S> s.skip(long);

Stream <S> s.unordered ();

Stream <S> s.parallel ();

Stream <S> s.sequential ();

Slide 26/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 49: JDK8: Stream style

Terminal Operations a.k.a. PROFIT

Slide 27/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 50: JDK8: Stream style

Terminal Operations

Terminal operations yield final result

Parallel or sequential execution

Terminal operations ’flavors’:iteration: forEach, iteratorsearching: findFirst, findAnymatching: allMatch, anyMatch, noneMatchaggregation:

𝑟𝑒𝑑𝑢𝑐𝑡𝑖𝑜𝑛𝑐𝑜𝑙𝑙𝑒𝑐𝑡𝑜𝑟𝑠

Slide 28/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 51: JDK8: Stream style

Short-circuiting

Do not consume the entire stream, drop it on the floor asnecessary

May operate infinite streams

find*, *Match, limite.g.:

int v = Stream.iterate(1, i -> i+1)

.filter( i % 2 == 0)

.findFirst (). get();

Slide 29/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 52: JDK8: Stream style

Iteration

Process each stream element:

IntStream.range(0, 100)

.forEach(System.out:: println );

Convert to old style iterator1:

Iterator <Integer > =

Stream.iterate(0, i -> i + 1)

.limit (100)

.iterator ();

1for compatibilitySlide 30/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 53: JDK8: Stream style

Example

How to compute a sum over Stream<Integer>?

public int getSum(Stream <Integer > s){

int sum;

s.forEach( i -> sum += i);

return sum;

}

Slide 31/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 54: JDK8: Stream style

Example

How to compute a sum over Stream<Integer>?

public int getSum(Stream <Integer > s){

int sum;

s.forEach( i -> sum += i);

return sum;

}

Slide 31/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 55: JDK8: Stream style

Example

How to compute a sum over Stream<Integer>?

public int getSum(Stream <Integer > s){

int sum;

s.forEach( i -> sum += i); // Compile error

return sum;

}

Slide 32/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 56: JDK8: Stream style

Example

How to compute a sum over Stream<Integer>?

public int getSum(Stream <Integer > s){

int[] sum = new int [1];

s.forEach( i -> sum[0] += i);

return sum [0];

}

Slide 33/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 57: JDK8: Stream style

Example

Result?

Stream <Integer > s = IntStream.range(0, 100)

.mapToObj(i -> 1);

System.out.println(getSum(s));

100

Stream <Integer > s = IntStream.range(0, 100)

.mapToObj(i -> 1)

.parallel ();

System.out.println(getSum(s));

79, 63, 100, ...

Slide 34/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 58: JDK8: Stream style

Example

Result?

Stream <Integer > s = IntStream.range(0, 100)

.mapToObj(i -> 1);

System.out.println(getSum(s));

100

Stream <Integer > s = IntStream.range(0, 100)

.mapToObj(i -> 1)

.parallel ();

System.out.println(getSum(s));

79, 63, 100, ...

Slide 34/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 59: JDK8: Stream style

Example

Result?

Stream <Integer > s = IntStream.range(0, 100)

.mapToObj(i -> 1);

System.out.println(getSum(s));

100

Stream <Integer > s = IntStream.range(0, 100)

.mapToObj(i -> 1)

.parallel ();

System.out.println(getSum(s));

79, 63, 100, ...

Slide 34/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 60: JDK8: Stream style

Example

Result?

Stream <Integer > s = IntStream.range(0, 100)

.mapToObj(i -> 1);

System.out.println(getSum(s));

100

Stream <Integer > s = IntStream.range(0, 100)

.mapToObj(i -> 1)

.parallel ();

System.out.println(getSum(s));

79, 63, 100, ...Slide 34/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 61: JDK8: Stream style

Reduction

Take a stream and make a scalar value:

Stream <Integer > s;

Integer sum = s.reduce(0, (x, y) -> x + y);

Some operations return Optional<T>:

Stream <Integer > s;

Optional <Integer > sum = s.reduce ((x, y) -> x + y);

Slide 35/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 62: JDK8: Stream style

Reduction

Take a stream and make a scalar value:

Stream <Integer > s;

Integer sum = s.reduce(0, (x, y) -> x + y);

Some operations return Optional<T>:

Stream <Integer > s;

Optional <Integer > sum = s.reduce ((x, y) -> x + y);

Slide 35/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 63: JDK8: Stream style

Reduction

Stream <T> {

...

<U> U reduce(U identity ,

BiFunction <U,T,U> accumulator ,

BinaryOperator <U> combiner)

...

}

Slide 36/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 64: JDK8: Stream style

Collectors

A.k.a. mutable reduction operationsAccumulate elements into a mutable result container:

List <Integer > list = IntStream.range(0, 100)

.boxed ()

.collect(Collectors.toList ());

int[] ints = IntStream.range(0, 100). toArray ();

Complex collections:

Map <Integer ,Integer > map = IntStream.range(0, 100)

.boxed (). collect(

Collectors.toConcurrentMap(

k -> k % 42, v -> v, (a, b) -> b

)

);

Slide 37/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 65: JDK8: Stream style

Collectors

A.k.a. mutable reduction operationsAccumulate elements into a mutable result container:

List <Integer > list = IntStream.range(0, 100)

.boxed ()

.collect(Collectors.toList ());

int[] ints = IntStream.range(0, 100). toArray ();

Complex collections:

Map <Integer ,Integer > map = IntStream.range(0, 100)

.boxed (). collect(

Collectors.toConcurrentMap(

k -> k % 42, v -> v, (a, b) -> b

)

);Slide 37/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 66: JDK8: Stream style

java.util.stream.Collectors

More than 30 predefined collectors, e.g.:

collector => result of Stream<T>.collect(collector)

toList () => List

toSet() => Set

toCollection(Supplier <Collection <T>>) => Collection <T>

partitioningBy(Predicate <T>) => Map <Boolean , List <T>>

groupingBy(Function <T,K>) => Map <K, List <T>>>

toMap(Function <T,K>,

Function <T,U>) => Map <K,U>

Slide 38/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 67: JDK8: Stream style

Collectors

String [] a = new String []{"a", "b", "c"};

Hot to get "a,b,c"?

Arrays.stream(a). collect(Collectors.joining(","));

FYI: java.util.StringJoiner

Slide 39/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 68: JDK8: Stream style

Collectors

String [] a = new String []{"a", "b", "c"};

Hot to get "a,b,c"?

Arrays.stream(a). collect(Collectors.joining(","));

FYI: java.util.StringJoiner

Slide 39/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 69: JDK8: Stream style

Collectors

String [] a = new String []{"a", "b", "c"};

Hot to get "a,b,c"?

Arrays.stream(a). collect(Collectors.joining(","));

FYI: java.util.StringJoiner

Slide 39/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 70: JDK8: Stream style

Collectors

Stream <T> {

...

<R> R collect(Supplier <R> supplier ,

BiConsumer <R, T> accumulator ,

BiConsumer <R, R> combiner)

...

}

Slide 40/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 71: JDK8: Stream style

Collectors

Stream <T> s;

List <T> l = s.collect(Collectors.toList ());

l = collect( () -> new ArrayList <>(),

(list , t) -> list.add(t),

(l1 , l2) -> l1.addAll(l2));

l = collect( ArrayList ::new , List::add , List:: addAll );

a

Slide 41/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 72: JDK8: Stream style

Collectors

Stream <T> s;

List <T> l = s.collect(Collectors.toList ());

l = collect( () -> new ArrayList <>(),

(list , t) -> list.add(t),

(l1 , l2) -> l1.addAll(l2));

l = collect( ArrayList ::new , List::add , List:: addAll );

a

Slide 41/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 73: JDK8: Stream style

Parallelism

Slide 42/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 74: JDK8: Stream style

Parallelism

Lots of sources are naturally splittable

Lots of operations are well parallelizable

Streams will do it for us

“ForkJoinPool inside”

Have to ask for the parallelism explicitly

int v = list.parallelStream ()

.reduce(Math::max)

.get();

Slide 43/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 75: JDK8: Stream style

Explicit parallelism

Q: Why not implicit?A: Final speedup depends on:

𝑁 – number of source elements

𝑄 – cost of operation

𝑃 – available HW parallelism

𝐶 – number of concurrent clients

We know 𝑁 .We can estimate 𝑃 .

We can somehow cope with 𝐶𝑄 is almost not predictable.

Slide 44/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 76: JDK8: Stream style

Thank you!

Slide 45/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 77: JDK8: Stream style

Q & A ?

Slide 46/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 78: JDK8: Stream style

Appendix

Slide 47/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 79: JDK8: Stream style

Spliterator

Slide 48/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 80: JDK8: Stream style

Spliterator

interface Spliterator <T> {

...

long estimateSize (); // Long.MAX_VALUE if unknown

boolean tryAdvance(Consumer <T> action );

Spliterator <T> trySplit ();

int characteristics ();

...

}

Slide 49/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 81: JDK8: Stream style

Spliterator’s characteristic

ORDERED

DISTINCT

SORTED

SIZED

SUBSIZED

NONNULL

IMMUTABLE

CONCURRENT

Slide 50/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.

Page 82: JDK8: Stream style

Stream design

I like to look at this as having chosen a design center that recognizesthat sequential is a degenerate case of parallel, rather than treatingparallel as the “weird bonus mode”. I realize that this choice wascontroversial and definitely caused some compromises, but eventuallypeople will have to start to unlearn their sequential biases, andthere’s no time like the present.

(c) Brian Goetz

http://mail.openjdk.java.net/pipermail/lambda-dev/2014-February/011870.html

Slide 51/51. Copyright c○ 2014, Oracle and/or its affiliates. All rights reserved.