overview of java 8 streams (part 4) - vanderbilt …schmidt/cs891f/2018-pdfs/08-java...4 •every...

29
Overview of Java 8 Streams (Part 4) Douglas C. Schmidt [email protected] www.dre.vanderbilt.edu/~schmidt Professor of Computer Science Institute for Software Integrated Systems Vanderbilt University Nashville, Tennessee, USA

Upload: others

Post on 15-May-2020

15 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

Overview of Java 8 Streams (Part 4)

Douglas C. [email protected]

www.dre.vanderbilt.edu/~schmidt

Professor of Computer Science

Institute for Software

Integrated Systems

Vanderbilt University

Nashville, Tennessee, USA

Page 2: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

2

Learning Objectives in this Part of the Lesson• Understand the structure & functionality of Java 8 streams, e.g.,

• Fundamentals of streams

• Common stream aggregate operations

• “Splittable iterators” (Spliterators)

• Terminating a stream

Page 3: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

3

Terminating a Stream

Page 4: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

4

• Every stream finishes with a terminal operation that yields a non-stream result

Intermediate operation (behavior f)

Intermediate operation (behavior g)

Terminal operation (behavior h)

Output f(x)

Output g(f(x))

Input x

Terminating a Stream

See github.com/douglascraigschmidt/LiveLessons/tree/master/Java8/ex12

Stream

.of("horatio",

"laertes",

"Hamlet", ...)

.filter(s -> toLowerCase

(s.charAt(0)) == 'h')

.map(this::capitalize)

.sorted()

.forEach(System.out::println);

Page 5: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

5

• Every stream finishes with a terminal operation that yields a non-stream result, e.g.

• No value at all

• i.e., only side-effects!

Terminating a Stream

Page 6: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

6

• Every stream finishes with a terminal operation that yields a non-stream result, e.g.

• No value at all

• The result of a reduction operation

Terminating a Stream

See docs.oracle.com/javase/tutorial/collections/streams/reduction.html

Page 7: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

7

• Several terminal operations returnno value at all

Terminating a Streamvoid runForEach() {

...

Stream

.of("horatio", "laertes",

"Hamlet", ...)

.filter(s -> toLowerCase

(s.charAt(0)) == 'h')

.map(this::capitalize)

.sorted()

.forEach

(System.out::println);

...

See github.com/douglascraigschmidt/LiveLessons/tree/master/Java8/ex12

Page 8: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

8

• Several terminal operations returnno value at all

Terminating a Stream

See docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#forEach

void runForEach() {

...

Stream

.of("horatio", "laertes",

"Hamlet", ...)

.filter(s -> toLowerCase

(s.charAt(0)) == 'h')

.map(this::capitalize)

.sorted()

.forEach

(System.out::println);

...

Performs the designated action on each element of this stream

Page 9: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

9

• Several terminal operations returnno value at all

Terminating a Streamvoid runForEach() {

List<String> results =

new ArrayList<>();

Stream

.of("horatio", "laertes",

"Hamlet", ...)

.filter(s -> toLowerCase

(s.charAt(0)) == 'h')

.map(this::capitalize)

.sorted()

.forEach

(results::add);

...

The lambda passed to forEach() is allowed to have side-effects

See www.logicbig.com/tutorials/core-java-tutorial/java-util-stream/side-effects

Page 10: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

10

• Several terminal operations returnno value at all

Terminating a Streamvoid runForEach() {

List<String> results =

new ArrayList<>();

Stream

.of("horatio", "laertes",

"Hamlet", ...)

.parallel()

.filter(s -> toLowerCase

(s.charAt(0)) == 'h')

.map(this::capitalize)

.sorted()

.forEach

(results::add);

...

Avoid using forEach() with side-effects in a parallel stream!!!

See docs.oracle.com/javase/tutorial/collections/streams/parallelism.html#side_effects

Page 11: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

11

• Other terminal operations returnthe result of a reduction operation

Terminating a Stream

See docs.oracle.com/javase/tutorial/collections/streams/reduction.html

void runCollectTo*() {

List<String> characters =

Arrays.asList("horatio",

"laertes",

"Hamlet", ...);

...<String> results =

characters

.stream()

.filter(s ->

toLowerCase(…) =='h')

.map(this::capitalize)

.sorted()

.collect(...); ...

Page 12: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

12See docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#collect

• Other terminal operations returnthe result of a reduction operation, e.g.

• a collection

void runCollectTo*() {

List<String> characters =

Arrays.asList("horatio",

"laertes",

"Hamlet", ...);

...<String> results =

characters

.stream()

.filter(s ->

toLowerCase(…) =='h')

.map(this::capitalize)

.sorted()

.collect(...); ...

Terminating a Stream

Performs a mutable reduction on all elements of this stream using some type of collector

Page 13: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

13See docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html

• Other terminal operations returnthe result of a reduction operation, e.g.

• a collection

void runCollectTo*() {

List<String> characters =

Arrays.asList("horatio",

"laertes",

"Hamlet", ...);

...<String> results =

characters

.stream()

.filter(s ->

toLowerCase(…) =='h')

.map(this::capitalize)

.sorted()

.collect(...); ...

Terminating a Stream

A collector performs reduction operations, e.g., summarizing elements according to various criteria, accumulating elements into various types of collections, etc.

Page 14: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

14See docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#toList

• Other terminal operations returnthe result of a reduction operation, e.g.

• a collection

void runCollectToList() {

List<String> characters =

Arrays.asList("horatio",

"laertes",

"Hamlet, ...);

List<String> results =

characters

.stream()

.filter(s ->

toLowerCase(…) =='h')

.map(this::capitalize)

.sorted()

.collect(toList()); ...

Terminating a Stream

Collect the results into a ArrayList

Page 15: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

15

• Other terminal operations returnthe result of a reduction operation, e.g.

• a collection

void runCollectToSet() {

List<String> characters =

Arrays.asList("horatio",

"laertes",

"Hamlet", ...);

Set<String> results =

characters

.stream()

.filter(s ->

toLowerCase(…) =='h')

.map(this::capitalize)

.collect(toSet()); ...

Terminating a Stream

Collect the results into a HashSet,which has no duplicate entries

See docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#toSet

Page 16: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

16

• Other terminal operations returnthe result of a reduction operation, e.g.

• a collection

void runCollectToMap() {

List<String> characters =

Arrays.asList("horatio",

"laertes",

"Hamlet", ...);

Map<String, Integer> results =

characters

.stream()

.filter(s ->

toLowerCase(…) =='h')

.map(this::capitalize)

.collect(toMap(identity(),

String::length,

Integer::sum));

...

Terminating a Stream

Collect results into a HashMap, along with the length of (merged duplicate) entries

See docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#toMap

Page 17: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

17

• Other terminal operations returnthe result of a reduction operation, e.g.

• a collection

void runCollectGroupingBy() {

List<String> characters =

Arrays.asList("horatio",

"laertes",

"Hamlet", ...);

Map<String, Long> results =

...

.collect

(groupingBy

(identity(),

TreeMap::new,

summingLong

(String::length)));

...

Collect the results into a TreeMapby grouping elements according to name (key) & name length (value)

Terminating a Stream

See docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#groupingBy

Page 18: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

18

• Other terminal operations returnthe result of a reduction operation, e.g.

• a collection

void runCollectGroupingBy() {

List<String> characters =

Arrays.asList("horatio",

"laertes",

"Hamlet", ...);

Map<String, Long> results =

...

.collect

(groupingBy

(identity(),

TreeMap::new,

summingLong

(String::length)));

...

Terminating a Stream

groupingBy() partitions a stream via a “classifier” function, e.g., by the identity() function that always

returns its input argument

See docs.oracle.com/javase/8/docs/api/java/util/function/Function.html#identity

Page 19: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

19

• Other terminal operations returnthe result of a reduction operation, e.g.

• a collection

void runCollectGroupingBy() {

List<String> characters =

Arrays.asList("horatio",

"laertes",

"Hamlet", ...);

Map<String, Long> results =

...

.collect

(groupingBy

(identity(),

TreeMap::new,

summingLong

(String::length)));

...

Terminating a Stream

A factory supplier is used to create the type of map

Page 20: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

20

• Other terminal operations returnthe result of a reduction operation, e.g.

• a collection

void runCollectGroupingBy() {

List<String> characters =

Arrays.asList("horatio",

"laertes",

"Hamlet", ...);

Map<String, Long> results =

...

.collect

(groupingBy

(identity(),

TreeMap::new,

summingLong

(String::length)));

...

Terminating a Stream

A “downstream collector” defines a collector applied by the Java runtime to the results of an earlier collector

See docs.oracle.com/javase/tutorial/collections/streams/reduction.html

Page 21: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

21

• Other terminal operations returnthe result of a reduction operation, e.g.

• a collection

void runCollectReduce() {

Map<String, Long>

matchingCharactersMap =

Pattern.compile(",")

.splitAsStream

("horatio,Hamlet,...")

...

.collect

(groupingBy

(identity(),

TreeMap::new,

summingLong

(String::length)));

Terminating a Stream

Convert a string into a stream via regular expression splitting!

See docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html#splitAsStream

Page 22: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

22

• Other terminal operations returnthe result of a reduction operation, e.g.

• a collection

void runCollectReduce() {

Map<String, Long>

matchingCharactersMap =

Pattern.compile(",")

.splitAsStream

("horatio,Hamlet,...")

...

.collect

(groupingBy

(identity(),

TreeMap::new,

summingLong

(String::length)));

Terminating a Stream

See docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#groupingBy

Collect the results into a TreeMapby grouping elements according to name (key) & name length (value)

Page 23: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

23See docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#reduce

• Other terminal operations returnthe result of a reduction operation, e.g.

• a collection

• a primitive value

void runCollectReduce() {

Map<String, Long>

matchingCharactersMap =

...

long countOfNameLengths =

matchingCharactersMap

.values()

.stream()

.reduce(0L,

(x, y) -> x + y);

Terminating a Stream

Sum up the lengths of all character names in Hamlet

Page 24: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

24

• Other terminal operations returnthe result of a reduction operation, e.g.

• a collection

• a primitive value

0 is the “identity,” i.e., the initial value of the reduction & the default result if there are no elements in the stream

void runCollectReduce() {

Map<String, Long>

matchingCharactersMap =

...

long countOfNameLengths =

matchingCharactersMap

.values()

.stream()

.reduce(0L,

(x, y) -> x + y);

Terminating a Stream

Page 25: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

25

void runCollectReduce() {

Map<String, Long>

matchingCharactersMap =

...

long countOfNameLengths =

matchingCharactersMap

.values()

.stream()

.reduce(0L,

(x, y) -> x + y);

• Other terminal operations returnthe result of a reduction operation, e.g.

• a collection

• a primitive value

This lambda is the “accumulator,” which is a stateless function that combines two values into a single (immutable) “reduced” value

Terminating a Stream

Page 26: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

26

• Other terminal operations returnthe result of a reduction operation, e.g.

• a collection

• a primitive value

There’s a 3 parameter “map/reduce” version of reduce() that’s used in parallel streams

void runCollectReduce() {

Map<String, Long>

matchingCharactersMap =

...

long countOfNameLengths =

matchingCharactersMap

.values()

.parallelStream()

.reduce(0L,

(x, y) -> x + y,

(x, y) -> x + y);

See www.youtube.com/watch?v=oWlWEKNM5Aw

Terminating a Stream

Page 27: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

27

• Other terminal operations returnthe result of a reduction operation, e.g.

• a collection

• a primitive value

There’s a sum() method that simplifies the use of reduce()

void runCollectReduce() {

Map<String, Long>

matchingCharactersMap =

...

long countOfNameLengths =

matchingCharactersMap

.values()

.stream()

.sum()

Terminating a Stream

See docs.oracle.com/javase/8/docs/api/java/util/stream/LongStream.html#sum

Page 28: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

28

• Other terminal operations returnthe result of a reduction operation, e.g.

• a collection

• a primitive value

Terminating a Stream

Intermediate operation (behavior f)

Output f(x)

Output g(f(x))

Intermediate operation (behavior g)

Terminal operation (behavior h)

Input x

collect() & reduce() terminal operations work seamlessly with parallel streams

parallelStream()

Page 29: Overview of Java 8 Streams (Part 4) - Vanderbilt …schmidt/cs891f/2018-PDFs/08-Java...4 •Every stream finishes with a terminal operation that yields a non-stream result Intermediate

29

End of Overview of Java 8 Streams (Part 4)