Top Banner
Harnessing the power of Java 8 Streams Praveer Gupta
47

Harnessing the Power of Java 8 Streams

Apr 13, 2017

Download

Software

IndicThreads
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Harnessing the Power of Java 8 Streams

Harnessing the power of

Java 8 StreamsPraveer Gupta

Page 2: Harnessing the Power of Java 8 Streams

Default Methods

Lambda Expressions

Streams

Date-Time API

CompletableFuture

Optional

Page 3: Harnessing the Power of Java 8 Streams

helps to make a strategic decision about what programming language should be adopted

when starting to build a new software system

Java 8 released on Mar 18, 2014

Page 4: Harnessing the Power of Java 8 Streams

–Robert C. Martin

“There are two parts to learning craftsmanship: knowledge and work.

You must gain the knowledge of principles, patterns, practices, and heuristics that a craftsman knows,

and you must also grind that knowledge

into your fingers, eyes, and gut by working hard and

practicing..”

Page 5: Harnessing the Power of Java 8 Streams

Stream

Intermediate Operators

Terminal Operators

Harnessing the power Java 8 Streams

Programming Paradigm Concepts

Page 6: Harnessing the Power of Java 8 Streams

Stream

Collectorscollectreduce

Intermediate Operators

Terminal Operators

computation creation Primitive Streams

stateless/stateful

Lazy & Short-Circuited

Harnessing the power Java 8 Streams

Declarative Programming

Internal Iteration

chained categories

Programming Paradigm Concepts

Page 7: Harnessing the Power of Java 8 Streams

Harnessing the power Java 8 Streams

Declarative Programming

Internal Iteration

Programming Paradigm Concepts

Page 8: Harnessing the Power of Java 8 Streams

DeclarativeSELECT NAME FROM PERSON WHERE AGE > 18;

List<String> adults = group.stream() .filter(p -> p.age() > 18) .map(Person::name) .collect(toList());

You declare what the program has to do and the library takes care of how to do it

Page 9: Harnessing the Power of Java 8 Streams

DeclarativeFocuses on

What

List<String> adults = new ArrayList<>();for (Person person: group) if (person.age() > 18) adults.add(person.name());

Focuses on How and

What

vs Imperative

List<String> adults = group.stream() .filter(p -> p.age() > 18) .map(Person::name) .collect(toList());

Page 10: Harnessing the Power of Java 8 Streams

Old way vs New wayfinal List<String> names = new ArrayList<>();for (Person p : group) if (p.age() > 18) names.add(p.name());return names;

return group.stream() .filter(p -> p.age() > 18) .map(Person::name) .collect(toList());

List<String> namesOfAdultsInTheGroup(List<Person> group) {

}

External Iteration

Internal Iteration

new declarative wayold imperative way

List<String> namesOfAdultsInTheGroup(List<Person> group) {

}

Page 11: Harnessing the Power of Java 8 Streams

Application of Streamsinterface CustomerRepository { List<Customer> findByCity(String cityName); }

API Definition

Page 12: Harnessing the Power of Java 8 Streams

Application of Streamsinterface CustomerRepository { Stream<Customer> findByCity(String cityName);}

try (Stream<String> stream = repository.findByCity(“Pune")) { return stream.filter(…).count();}

API Definition

Usage of the API

Consume items as they arrive Efficient memory usage

Page 13: Harnessing the Power of Java 8 Streams

Streamcomputation creation

Harnessing the power Java 8 Streams

Declarative Programming

Internal Iteration

Programming Paradigm Concepts

Page 14: Harnessing the Power of Java 8 Streams

Streama read-only sequence of elements

computational operations that will be performed in aggregate

Collectionefficient management of elements

efficient access to elements

Page 15: Harnessing the Power of Java 8 Streams

Stream Pipeline

StreamTerminal Operator

Ope

rato

r 1

Ope

rato

r 2

Ope

rato

r 3

Intermediate Operators

(Zero or more)

Page 16: Harnessing the Power of Java 8 Streams

StreamTerminal Operator

Ope

rato

r 1

Ope

rato

r 2

Ope

rato

r 3

Stream Pipeline

List<String> namesOfAdultsInTheGroup(List<Person> group) { return }

group.stream() .filter(p -> p.age() > 18) .map(Person::name) .collect(Collectors.toList());

Page 17: Harnessing the Power of Java 8 Streams

names

group

Stream<Person> Archer(22 years)

Barbara(17 years)

Daisy(25 years)

is person’s age > 18 ?

Stream<Person>

Stream<String>

map to name of person

collect into a list

group.stream()

.filter(p -> p.age() > 18)

.map(Person::name)

.collect( Collectors.toList());

Archer(22 years)

Barbara(17 years)

Daisy(25 years)

Archer(22 years)

Daisy(25 years)

Archer Daisy

Archer Daisy

Page 18: Harnessing the Power of Java 8 Streams

Creating StreamFrom CollectionList<String> list = Arrays.asList("a", "b", "c"); Stream<String> stream = list.stream();

String[] array = {"a", "b", "c"};Stream<String> stream = Arrays.stream(array);

Page 19: Harnessing the Power of Java 8 Streams

Creating StreamFrom an I/O Channeltry (Stream<Path> stream = Files.list(Paths.get(“.”));) { … }

Stream interface extends AutoCloseable

Page 20: Harnessing the Power of Java 8 Streams

Creating StreamUsing Generator FunctionsStream<Double> stream = Stream.generate(Math::random);

Stream<Integer> stream = Stream.iterate(0, n -> n + 3);

Both are unbounded

Page 21: Harnessing the Power of Java 8 Streams

Parallel StreamFrom CollectionList<String> list = Arrays.asList("a", "b", "c"); Stream<String> stream = list.parallelStream();

From another StreamStream<String> parallelStream = stream.parallel();

List<String> list = Arrays.asList("a", "b", "c"); Stream<String> stream = list.parallelStream();

Stream<String> parallelStream = stream.parallel();

Page 22: Harnessing the Power of Java 8 Streams

Parallel StreamHow does it work?

Splitting CombiningParallel Processing

Page 23: Harnessing the Power of Java 8 Streams

Parallel StreamPerformance ImpactAlways measure performance before using parallel

Stream size predictability & Amount of data

Decomposability of source data structure

Computational Cost

Page 24: Harnessing the Power of Java 8 Streams

Stream

Intermediate Operators

computation creation

stateless/stateful

Harnessing the power Java 8 Streams

Declarative Programming

Internal Iteration

chained categories

Programming Paradigm Concepts

Page 25: Harnessing the Power of Java 8 Streams

Intermediate Operators

StreamTerminal Operator

Ope

rato

r 1

Ope

rato

r 2

Ope

rato

r 3

Intermediate Operators

(Zero or more)

Page 26: Harnessing the Power of Java 8 Streams

Intermediate OperatorsCategoriesStream<Integer> stream = Stream.of(3, 2, 1);

Stream<Integer> filtered = stream.filter(n -> n % 2 == 0);

Filtering

Type of stream remains the same

Stream<Integer> filtered = stream.filter(n -> n % 2 == 0);

Page 27: Harnessing the Power of Java 8 Streams

Intermediate OperatorsCategoriesStream<Integer> stream = Stream.of(3, 2, 1);

Stream<String> mapped = stream.map(Object::toString);

Mapping

Type of stream gets altered (here Integer to String)

Stream<String> mapped = stream.map(Object::toString);

Page 28: Harnessing the Power of Java 8 Streams

Intermediate OperatorsCategoriesStream<Integer> stream = Stream.of(3, 2, 1);

Stream<Integer> sliced = stream.limit(1);

Slicing

Type of stream remains the same

Stream<Integer> sliced = stream.limit(1);

Page 29: Harnessing the Power of Java 8 Streams

Stream.of(1, 2, 3, 4) .peek(System.out::println) .filter(n -> n % 2 == 0);

Intermediate OperatorsLaziness

Stream.of(1, 2, 3, 4) .peek(System.out::println) .filter(n -> n % 2 == 0) .collect(toList());

Stream.of(1, 2, 3, 4) .peek(System.out::println) .filter(n -> n % 2 == 0);

Terminal operator is required to start stream processing

Stream.of(1, 2, 3, 4) .peek(System.out::println) .filter(n -> n % 2 == 0) .collect(toList());

Peek will not print anything

Page 30: Harnessing the Power of Java 8 Streams

Intermediate OperatorsShort-CircuitingStream.of(1, 2, 3, 4) .peek(System.out::println) .filter(n -> n % 2 == 0) .findFirst();

Stream will get short-circuited after the first element is found

Peek will print only 1 & 2

Stream.of(1, 2, 3, 4) .peek(System.out::println) .filter(n -> n % 2 == 0) .findFirst();

Page 31: Harnessing the Power of Java 8 Streams

Intermediate OperatorsStateless

vs Stateful

Stream.of(1, 2, 3, 4) .peek(System.out::println) .filter(n -> n % 2 == 0) .findFirst();

Stream.of(1, 2, 3, 4) .peek(System.out::println) .sorted(Comparator.reverseOrder()) .filter(n -> n % 2 == 0) .findFirst();

Will cause the whole stream

to be traversed

All operations are done on current value

in stream

Stream.of(1, 2, 3, 4) .peek(System.out::println) .sorted(Comparator.reverseOrder()) .filter(n -> n % 2 == 0) .findFirst();

Page 32: Harnessing the Power of Java 8 Streams

Stream

Collectorscollectreduce

Intermediate Operators

Terminal Operators

computation creation

stateless/stateful

Lazy & Short-Circuited

Harnessing the power Java 8 Streams

Declarative Programming

Internal Iteration

chained categories

Programming Paradigm Concepts

Page 33: Harnessing the Power of Java 8 Streams

Terminal Operators

Single Value Collection

Reduce Operation Collect Operation

Page 34: Harnessing the Power of Java 8 Streams

Terminal Operatorsreduce

<U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner);

Stream.of(3, 2, 1).reduce(0, Integer::sum, Integer::sum);

Stream.of(3, 2, 1).reduce(0, Integer::sum);

Immutable Reduction Process

<U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner);

<U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner);

<U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner);

Page 35: Harnessing the Power of Java 8 Streams

Terminal Operatorsreduce utility methodsOptional<Integer> max = Stream.of(1, 2, 3) .max(Comparator.naturalOrder());

boolean result = Stream.of(1, 2, 3) .anyMatch(n -> n > 2);

Optional<Integer> max = Stream.of(1, 2, 3) .max(Comparator.naturalOrder());

boolean result = Stream.of(1, 2, 3) .anyMatch(n -> n > 2);

Page 36: Harnessing the Power of Java 8 Streams

Terminal OperatorscollectMutable Reduction Process

Accumulates elements into a mutable result container

Stream.of("a", "b", "c").reduce("", String::concat);

String copying = Low Performance !!

Page 37: Harnessing the Power of Java 8 Streams

Terminal Operatorscollect

<R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner);

StringBuilder builder = Stream.of("a", "b", "c").collect( StringBuilder::new, StringBuilder::append, StringBuilder::append);

StringBuilder is the mutable container here

Page 38: Harnessing the Power of Java 8 Streams

Terminal OperatorsCollectors class

String joinedString = Stream.of(“a", "b", “c") .collect(Collectors.joining(", "));

IntSummaryStatistics statistics = group.stream() .collect(Collectors.summarizingInt(Person::age));

IntSummaryStatistics{count=10, sum=280, min=26, average=28.000000, max=30}

Output: a, b, c

String joinedString = Stream.of(“a", "b", “c") .collect(Collectors.joining(", "));

IntSummaryStatistics statistics = group.stream() .collect(Collectors.summarizingInt(Person::age));

Page 39: Harnessing the Power of Java 8 Streams

Terminal OperatorsDownstream Collectors

Map<Integer, List<Person>> result = group.stream() .collect(Collectors.groupingBy(Person::age, Collectors.toList()));

Map<Integer, List<Person>> result = group.stream() .collect(groupingBy(Person::age));

Divide into different age groups

Page 40: Harnessing the Power of Java 8 Streams

Terminal OperatorsDownstream Collectors

Map<Integer, Long> result = group.stream() .collect(groupingBy(Person::age, counting()));

Map<Integer, List<String>> result = group.stream() .collect(groupingBy(Person::age, mapping(Person::name, toList())));

Count of people in each age group

Names on people in each age group

Page 41: Harnessing the Power of Java 8 Streams

Stream

Collectorscollectreduce

Intermediate Operators

Terminal Operators

computation creation Primitive Streams

stateless/stateful

Lazy & Short-Circuited

Harnessing the power Java 8 Streams

Declarative Programming

Internal Iteration

chained categories

Programming Paradigm Concepts

Page 42: Harnessing the Power of Java 8 Streams

Primitive StreamsIntStream DoubleStreamLongStream

Avoid boxing and unboxing costs

Numeric operations are available

XXXFunction

XXXPredicateXXXSupplierXXXConsumer

XXXToXXXFunction

Primitive Functional Interfaces

Page 43: Harnessing the Power of Java 8 Streams

Primitive StreamsCreating from factory methods

IntStream intStream = IntStream.range(1, 10);

DoubleStream doubleStream = DoubleStream.of(1.0, 2.0);

LongStream longStream = LongStream.iterate(0L, n -> n + 4);

Generating a range of numbers

Stream of known set of numbers

Stream using iterative application of a function

Page 44: Harnessing the Power of Java 8 Streams

Stream<Person> stream = group.stream();

Primitive StreamsObtaining from Stream<T>

mapToXXX flatMapToXXX

IntStream intStream = stream.mapToInt(Person::age);

OptionalDouble averageAge = intStream.average();Specialized methods on Primitive Streams

IntStream intStream = stream.mapToInt(Person::age);

Page 45: Harnessing the Power of Java 8 Streams

Primitive StreamsConverting back to Stream<T>

Stream<Integer> boxed = IntStream.of(1, 2, 3).boxed();Stream<Integer> boxed = IntStream.of(1, 2, 3).boxed();

Page 46: Harnessing the Power of Java 8 Streams

Stream

Collectorscollectreduce

Intermediate Operators

Terminal Operators

computation creation Primitive Streams

stateless/stateful

Lazy & Short-Circuited

Harnessing the power Java 8 Streams

Declarative Programming

Internal Iteration

chained categories

Programming Paradigm Concepts

Page 47: Harnessing the Power of Java 8 Streams

Questions?

http://praveer09.github.io@praveerguptapraveer