SlideShare a Scribd company logo
Java 8
Functional features
2015-11-09 Rafał Rybacki
Agenda
1. functional paradigm
2. lambdas
3. functional interfaces
4. default methods
5. streams
a. parallel iteration
b. lazy evaluation
6. map & flat map
7. maps
Functional paradigm
● Treats computation as the evaluation of mathematical functions and
avoids changing-state and mutable data.
● Roots in lambda calculus
○ Alonzo Church developed concept in 1930
○ John McCarthy developed Lisp in 1950s
Functional concepts
● Referential transparency
○ Expression can be replaced by the value it returns
● Pure function
○ The result depends only on input value, not state
○ Evaluation does not cause side-effects
● Idempotence
○ Operation with side effects that can be applied multiple time without changing the result
beyond initial application.
○ ex. HTTP GET, PUT, DELETED (without POST)
● Higher order function
○ Function that takes another function as argument
Functional concepts (2)
● Map
○ Apply function to collection items
● Reduce
○ Combine input collection into single value result
● Currying
○ Translation of function with multiple arguments into higher-order functions
Declarative vs imperative
● Imperative - instructions that changes state
○ Assembler
○ C
● Declarative - describe what you want
○ HTML
○ AngularJs (directives)
Declarative vs imperative
Imperative Declarative
getRemoteData("example.com", { data, error in
if error == nil {
parseData(data, { parsed, error in
if error == nil {
handleParsedData(parsed, { error in
if error != nil {
displayError(error)
}
})
} else {
displayError(error)
}
})
} else {
displayError(error)
}
}
getRemoteData("example.com")
.then(parseData)
.then(handleParsedData)
.onError(displayError)
Declarative vs imperative
● Imperative - “Please take the glass, pour the water and pass it to me.”
● Declarative - “I want to drink water.”
Declarative vs imperative
Declarative programming helps in:
● Direct translation of the business model into business logic
● Better readability of the business logic
● Better scalability for the program in terms of functionality (reusability)
● Easies testing - due to better isolation and loose coupling
● Less bugs (quality and safety - due to side effects and avoiding state)
Imperative is mainstream
Imperative programming paradigm is the mainstream.
Imperative is mainstream
Imperative programming paradigm is:
● the most popular,
● the easiest,
● delivers not best outcome in terms of maintenance,
Imperative programming is mainstream because all of us have been taught it
while learning - that’s why it’s mainstream.
Difficulties in declarative programming
● It requires separating small responsibilities
● It requires good quality, clear unit tests (instead of debugging)
● It requires trust in quality of the implementation
● It required transition in thinking (learning it)
getRemoteData("example.com")
.then(parseData)
.then(handleParsedData)
.onError(displayError)
Functional - disadvantages
● Performance of more complex algorithms is lower
● Sometimes side-effects are required
○ ex. storing in session
○ -> functional approach helps to split stateful and stateless parts
● For some algorithms it decreases readibility
Lambdas
Definition: Lambda is anonymous function.
● Function is first-class citizen
● Short syntax
String x = “Hello”;
Function y = System.out::println;
y.apply(x);
Lambdas
() -> {}
Lambdas
() -> {}
(input) -> {} input -> {}
Lambdas
() -> {}
(input) -> {}
() -> {output}
input -> {}
() -> output () -> {return output;}
Lambdas
() -> {}
(input) -> {}
() -> {output}
(input) -> {output}
input -> {}
() -> output () -> {return output;}
input -> output
Lambdas
() -> {}
(input) -> {}
() -> {output}
(input) -> {output}
input -> {}
() -> output () -> {return output;}
input -> output
(input1, input2) -> output
Lambdas - functional interfaces
Runnable r = () -> {}
Consumer c = (input) -> {}
Supplier s = () -> {output}
Function f = (input) -> {output}
Lambdas - functional interfaces
BiConsumer bc = (input1, input2) -> {}
UnaryOperator negate = integer -> -integer
BinaryOperator add = (int1, int2) -> int1 + int2
Predicate p = input -> boolean
BiPredicate bp = (input1, input2) -> boolean
Lambda under the hood
Anonymous function:
● Created in compiletime
● Resides in the same folder as enclosing class
Lambda:
1. On first run code is generated in runtime using invokedynamic
2. invokedynamic is replaced with code equivalent to anonymous class
3. Performance of generated code is the same as anonymous class
● Java 8 introduced new methods in interfaces, like:
● Implementation:
Default methods
Iterable.forEach(Consumer<? super T> action)
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
The goal:
● Allow Oracle to extend collection interfaces
● Allow everybody extend interfaces without breaking compatibility.
Is it useful?
● Not very often.
● Keep compatibility in case stateless method are added.
Default methods
● Problem known in languages with multiple inheritance (like C++)
Deadly diamond of death
interface A {
default void action() {
System.out.println("A");
}
}
interface B {
default void action() {
System.out.println("B");
}
}
interface AB extends A, B ?
● Problem:
● Solution:
Deadly diamond of death
interface A {
default void action() {
System.out.println("A");
}
}
interface B {
default void action() {
System.out.println("B");
}
}
interface AB extends A, B {
@Override
void action();
}
interface AB extends A, B {
@Override
default void action() {
A.super.action();
}
}
or
Streams
● Streams are for operations
● Collections are for storing.
Most often, it is required to process operations rather than store data.
Streams - useful methods
● map
● filter
● distinct
● skip, limit
● peek
● min, max
● count
● findAny, findFirst
users.stream()
.map(...)
.filter(...)
.distinct()
.skip(5)
.limit(10)
.peek(item -> System.out.print(item))
.count();
● Heavy operations pipelined:
Streams are lazy
final Stream<Integer> inputs = // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
IntStream.range(0, 10).boxed();
inputs
.map(new HeavyOperation("A"))
.map(new HeavyOperation("B"))
.map(new HeavyOperation("C"))
.filter(input -> input == 3)
.collect(toList());
● Heavy operation - prints to console
Streams are lazy
class HeavyOperation {
public Integer apply(Integer input) {
System.out.println("Heavy operation " + operationName + " for element " + input);
return input;
}
}
● Heavy operations on all items
Streams are lazy
final Stream<Integer> inputs =
IntStream.range(0, 10).boxed();
inputs
.map(new HeavyOperation("A"))
.map(new HeavyOperation("B"))
.map(new HeavyOperation("C"))
.collect(toList());
Heavy operation A for element 0
Heavy operation B for element 0
Heavy operation C for element 0
Heavy operation A for element 1
Heavy operation B for element 1
Heavy operation C for element 1
Heavy operation A for element 2
Heavy operation B for element 2
Heavy operation C for element 2
Heavy operation A for element 3
Heavy operation B for element 3
Heavy operation C for element 3
Heavy operation A for element 4
Heavy operation B for element 4
Heavy operation C for element 4
Heavy operation A for element 5
Heavy operation B for element 5
Heavy operation C for element 5
Heavy operation A for element 6
Heavy operation B for element 6
Heavy operation C for element 6
Heavy operation A for element 7
Heavy operation B for element 7
Heavy operation C for element 7
Heavy operation A for element 8
Heavy operation B for element 8
Heavy operation C for element 8
Heavy operation A for element 9
Heavy operation B for element 9
Heavy operation C for element 9
CONSOLE OUTPUT
● Only required operations
Streams are lazy
final Stream<Integer> inputs =
IntStream.range(0, 10).boxed();
inputs
.map(new HeavyOperation("A"))
.map(new HeavyOperation("B"))
.map(new HeavyOperation("C"))
.filter(input -> input == 3)
.findFirst();
Heavy operation A for element 0
Heavy operation B for element 0
Heavy operation C for element 0
Heavy operation A for element 1
Heavy operation B for element 1
Heavy operation C for element 1
Heavy operation A for element 2
Heavy operation B for element 2
Heavy operation C for element 2
Heavy operation A for element 3
Heavy operation B for element 3
Heavy operation C for element 3
CONSOLE OUTPUT
● No collection operation
Streams are lazy
final Stream<Integer> inputs =
IntStream.range(0, 10).boxed();
inputs
.map(new HeavyOperation("A"))
.map(new HeavyOperation("B"))
.map(new HeavyOperation("C"))
.filter(input -> input == 3);
CONSOLE OUTPUT
● Collection function
● Reduction function (fold function)
list
.stream()
.collect(toList());
Streams - operations output
int sum = integers
.stream()
.sum();
int sum = integers
.stream()
.reduce(0, (total, item) -> total + item);
Streams - parallel execution
List inputs = ...
inputs
.parallelStream()
.map(new HeavyOperation("A"))
.map(new HeavyOperation("B"))
.map(new HeavyOperation("C"))
.findFirst();
Streams - collectors
● Aggregating
● Comparing
● Grouping
List<User> allUsers = users.stream().collect(toList());
User userWithMaxLogins = users.stream()
.collect( maxBy( comparing(User::loginsCount) ) );
Map<Role, List<User>> usersPerRole = users.stream()
.collect( groupingBy( User::getRole) );
Streams - collectors
● Partitioning
Map<Boolean, List<User>> activeUsers = stream
.collect(
partitioningBy(
user -> user.getLoginsCount() > 0));
Flat mapping
● Stream: Combine stream of streams into single stream.
● Optional: Combine optional of optional into single optional.
○ A pipeline of operations out of which any may fail
Flat mapping
private Optional<Banana> fetchBananaImperative() {
Optional<Island> island = findIsland();
boolean noIslandFound = !island.isPresent();
if (noIslandFound) {
return empty();
}
Optional<Jungle> jungle = findJungle(island.get());
boolean noJungleFound = !jungle.isPresent();
if (noJungleFound) {
return empty();
}
Optional<Tree> tree = findTree(jungle.get());
boolean noTreeFound = !tree.isPresent();
if (noTreeFound) {
return empty();
}
Optional<Banana> banana = findBanana(tree.get());
boolean noBananaFound = !banana.isPresent();
if (noBananaFound) {
return empty();
}
return banana;
}
Flat mapping
private Optional<Banana> fetchBananaImperative() {
Optional<Island> island = findIsland();
boolean noIslandFound = !island.isPresent();
if (noIslandFound) {
return empty();
}
Optional<Jungle> jungle = findJungle(island.get());
boolean noJungleFound = !jungle.isPresent();
if (noJungleFound) {
return empty();
}
Optional<Tree> tree = findTree(jungle.get());
boolean noTreeFound = !tree.isPresent();
if (noTreeFound) {
return empty();
}
Optional<Banana> banana = findBanana(tree.get());
boolean noBananaFound = !banana.isPresent();
if (noBananaFound) {
return empty();
}
return banana;
}
private Optional<Banana> fetchBananaFluent() {
Optional<Island> islandOptional = findIsland();
Optional<Banana> banana = islandOptional
.flatMap(island -> findJungle(island))
.flatMap(jungle -> findTree(jungle))
.flatMap(tree -> findBanana(tree));
return banana;
}
Map - new methods
map.compute(key, (key, value) -> newValue);
map.putIfAbsent(key, value);
map.replace(key, value);
map.replace(key, oldValue, newValue);
map.getOrDefault(key, defaultValue);
map.merge(key, newValue, (oldValue, newValue) -> mergedValue);
Lambda vs method reference
Optional<Banana> banana = islandOptional
.flatMap(island -> findJungle(island))
.flatMap(jungle -> findTree(jungle))
.flatMap(tree -> findBanana(tree));
Lambda vs method reference
Optional<Banana> banana = islandOptional
.flatMap(island -> findJungle(island))
.flatMap(jungle -> findTree(jungle))
.flatMap(tree -> findBanana(tree));
Optional<Banana> banana = islandOptional
.flatMap(island -> findJungle(island))
.flatMap(Jungle::getTree)
.flatMap(tree -> tree.getBanana());
● Syntax may affect readibility
Lambda vs method reference
Options:
● allow mixing lambda and method reference
● only lambdas
Optional<Banana> banana = islandOptional
.flatMap(island -> findJungle(island))
.flatMap(Jungle::getTree)
.flatMap(tree -> tree.getBanana());
Thanks.

More Related Content

PDF
Node js
PPTX
Learning C++ - Functions in C++ 3
PDF
Monads in Swift
PPTX
functions of C++
PPT
C++ functions presentation by DHEERAJ KATARIA
PPT
Lecture#6 functions in c++
PPT
Functions in C++
PPTX
Cs1123 8 functions
Node js
Learning C++ - Functions in C++ 3
Monads in Swift
functions of C++
C++ functions presentation by DHEERAJ KATARIA
Lecture#6 functions in c++
Functions in C++
Cs1123 8 functions

What's hot (20)

PDF
Operator_Overloaing_Type_Conversion_OOPC(C++)
PPTX
Functions in C++ (OOP)
PPTX
User Defined Functions in MATLAB part 2
PDF
Fun with Lambdas: C++14 Style (part 1)
PPTX
C and C++ functions
PDF
M11 operator overloading and type conversion
PPTX
Lambda Expressions in C++
PPT
Operator Overloading
PDF
Cocoa heads 09112017
PPT
FUNCTIONS IN c++ PPT
PDF
The Ring programming language version 1.5.4 book - Part 21 of 185
PDF
Advanced functional programing in Swift
PPTX
Functions in C++
PPTX
A quick introduction to R
PPTX
Chapter 4
PPTX
operator overloading
PDF
Embedding Generic Monadic Transformer into Scala. [Tfp2022]
PPT
Functions in C++
PDF
The Ring programming language version 1.8 book - Part 26 of 202
PPTX
operator overloading & type conversion in cpp over view || c++
Operator_Overloaing_Type_Conversion_OOPC(C++)
Functions in C++ (OOP)
User Defined Functions in MATLAB part 2
Fun with Lambdas: C++14 Style (part 1)
C and C++ functions
M11 operator overloading and type conversion
Lambda Expressions in C++
Operator Overloading
Cocoa heads 09112017
FUNCTIONS IN c++ PPT
The Ring programming language version 1.5.4 book - Part 21 of 185
Advanced functional programing in Swift
Functions in C++
A quick introduction to R
Chapter 4
operator overloading
Embedding Generic Monadic Transformer into Scala. [Tfp2022]
Functions in C++
The Ring programming language version 1.8 book - Part 26 of 202
operator overloading & type conversion in cpp over view || c++
Ad

Similar to Java 8 - functional features (20)

PDF
Towards hasktorch 1.0
PDF
Java 8
PDF
Functional Programming 101 for Java 7 Developers
PDF
Functional programming 101
PPTX
PPTX
Functional Programming in Java
PPT
Lecture05
PPTX
Chp8_C++_Functions_Part2_User-defined functions.pptx
PPT
443600107-1-Introduction-to education -C-ppt
PPT
443600107-1-Introduction-to-C-ppt (1).ppt
PDF
Functional Programming in Java - Code for Maintainability
PPTX
MADlib Architecture and Functional Demo on How to Use MADlib/PivotalR
PDF
Object Oriented Programming using C++ - Part 3
PDF
Functionssssssssssssssssssssssssssss.pdf
PPTX
Functional programming with Ruby - can make you look smart
PPTX
PPTX
Programming For Engineers Functions - Part #1.pptx
PDF
Scala qq
DOC
Cs2312 OOPS LAB MANUAL
Towards hasktorch 1.0
Java 8
Functional Programming 101 for Java 7 Developers
Functional programming 101
Functional Programming in Java
Lecture05
Chp8_C++_Functions_Part2_User-defined functions.pptx
443600107-1-Introduction-to education -C-ppt
443600107-1-Introduction-to-C-ppt (1).ppt
Functional Programming in Java - Code for Maintainability
MADlib Architecture and Functional Demo on How to Use MADlib/PivotalR
Object Oriented Programming using C++ - Part 3
Functionssssssssssssssssssssssssssss.pdf
Functional programming with Ruby - can make you look smart
Programming For Engineers Functions - Part #1.pptx
Scala qq
Cs2312 OOPS LAB MANUAL
Ad

Recently uploaded (20)

PDF
wealthsignaloriginal-com-DS-text-... (1).pdf
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PDF
Design an Analysis of Algorithms II-SECS-1021-03
PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PDF
AI in Product Development-omnex systems
PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PDF
Odoo Companies in India – Driving Business Transformation.pdf
PDF
How Creative Agencies Leverage Project Management Software.pdf
PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
PDF
System and Network Administration Chapter 2
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PPTX
ai tools demonstartion for schools and inter college
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PPTX
CHAPTER 2 - PM Management and IT Context
PPTX
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
wealthsignaloriginal-com-DS-text-... (1).pdf
Navsoft: AI-Powered Business Solutions & Custom Software Development
Design an Analysis of Algorithms II-SECS-1021-03
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
Design an Analysis of Algorithms I-SECS-1021-03
AI in Product Development-omnex systems
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
Upgrade and Innovation Strategies for SAP ERP Customers
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
Odoo Companies in India – Driving Business Transformation.pdf
How Creative Agencies Leverage Project Management Software.pdf
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
System and Network Administration Chapter 2
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
ai tools demonstartion for schools and inter college
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
Internet Downloader Manager (IDM) Crack 6.42 Build 41
CHAPTER 2 - PM Management and IT Context
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)

Java 8 - functional features

  • 2. Agenda 1. functional paradigm 2. lambdas 3. functional interfaces 4. default methods 5. streams a. parallel iteration b. lazy evaluation 6. map & flat map 7. maps
  • 3. Functional paradigm ● Treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data. ● Roots in lambda calculus ○ Alonzo Church developed concept in 1930 ○ John McCarthy developed Lisp in 1950s
  • 4. Functional concepts ● Referential transparency ○ Expression can be replaced by the value it returns ● Pure function ○ The result depends only on input value, not state ○ Evaluation does not cause side-effects ● Idempotence ○ Operation with side effects that can be applied multiple time without changing the result beyond initial application. ○ ex. HTTP GET, PUT, DELETED (without POST) ● Higher order function ○ Function that takes another function as argument
  • 5. Functional concepts (2) ● Map ○ Apply function to collection items ● Reduce ○ Combine input collection into single value result ● Currying ○ Translation of function with multiple arguments into higher-order functions
  • 6. Declarative vs imperative ● Imperative - instructions that changes state ○ Assembler ○ C ● Declarative - describe what you want ○ HTML ○ AngularJs (directives)
  • 7. Declarative vs imperative Imperative Declarative getRemoteData("example.com", { data, error in if error == nil { parseData(data, { parsed, error in if error == nil { handleParsedData(parsed, { error in if error != nil { displayError(error) } }) } else { displayError(error) } }) } else { displayError(error) } } getRemoteData("example.com") .then(parseData) .then(handleParsedData) .onError(displayError)
  • 8. Declarative vs imperative ● Imperative - “Please take the glass, pour the water and pass it to me.” ● Declarative - “I want to drink water.”
  • 9. Declarative vs imperative Declarative programming helps in: ● Direct translation of the business model into business logic ● Better readability of the business logic ● Better scalability for the program in terms of functionality (reusability) ● Easies testing - due to better isolation and loose coupling ● Less bugs (quality and safety - due to side effects and avoiding state)
  • 10. Imperative is mainstream Imperative programming paradigm is the mainstream.
  • 11. Imperative is mainstream Imperative programming paradigm is: ● the most popular, ● the easiest, ● delivers not best outcome in terms of maintenance, Imperative programming is mainstream because all of us have been taught it while learning - that’s why it’s mainstream.
  • 12. Difficulties in declarative programming ● It requires separating small responsibilities ● It requires good quality, clear unit tests (instead of debugging) ● It requires trust in quality of the implementation ● It required transition in thinking (learning it) getRemoteData("example.com") .then(parseData) .then(handleParsedData) .onError(displayError)
  • 13. Functional - disadvantages ● Performance of more complex algorithms is lower ● Sometimes side-effects are required ○ ex. storing in session ○ -> functional approach helps to split stateful and stateless parts ● For some algorithms it decreases readibility
  • 14. Lambdas Definition: Lambda is anonymous function. ● Function is first-class citizen ● Short syntax String x = “Hello”; Function y = System.out::println; y.apply(x);
  • 16. Lambdas () -> {} (input) -> {} input -> {}
  • 17. Lambdas () -> {} (input) -> {} () -> {output} input -> {} () -> output () -> {return output;}
  • 18. Lambdas () -> {} (input) -> {} () -> {output} (input) -> {output} input -> {} () -> output () -> {return output;} input -> output
  • 19. Lambdas () -> {} (input) -> {} () -> {output} (input) -> {output} input -> {} () -> output () -> {return output;} input -> output (input1, input2) -> output
  • 20. Lambdas - functional interfaces Runnable r = () -> {} Consumer c = (input) -> {} Supplier s = () -> {output} Function f = (input) -> {output}
  • 21. Lambdas - functional interfaces BiConsumer bc = (input1, input2) -> {} UnaryOperator negate = integer -> -integer BinaryOperator add = (int1, int2) -> int1 + int2 Predicate p = input -> boolean BiPredicate bp = (input1, input2) -> boolean
  • 22. Lambda under the hood Anonymous function: ● Created in compiletime ● Resides in the same folder as enclosing class Lambda: 1. On first run code is generated in runtime using invokedynamic 2. invokedynamic is replaced with code equivalent to anonymous class 3. Performance of generated code is the same as anonymous class
  • 23. ● Java 8 introduced new methods in interfaces, like: ● Implementation: Default methods Iterable.forEach(Consumer<? super T> action) default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); } }
  • 24. The goal: ● Allow Oracle to extend collection interfaces ● Allow everybody extend interfaces without breaking compatibility. Is it useful? ● Not very often. ● Keep compatibility in case stateless method are added. Default methods
  • 25. ● Problem known in languages with multiple inheritance (like C++) Deadly diamond of death interface A { default void action() { System.out.println("A"); } } interface B { default void action() { System.out.println("B"); } } interface AB extends A, B ?
  • 26. ● Problem: ● Solution: Deadly diamond of death interface A { default void action() { System.out.println("A"); } } interface B { default void action() { System.out.println("B"); } } interface AB extends A, B { @Override void action(); } interface AB extends A, B { @Override default void action() { A.super.action(); } } or
  • 27. Streams ● Streams are for operations ● Collections are for storing. Most often, it is required to process operations rather than store data.
  • 28. Streams - useful methods ● map ● filter ● distinct ● skip, limit ● peek ● min, max ● count ● findAny, findFirst users.stream() .map(...) .filter(...) .distinct() .skip(5) .limit(10) .peek(item -> System.out.print(item)) .count();
  • 29. ● Heavy operations pipelined: Streams are lazy final Stream<Integer> inputs = // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 IntStream.range(0, 10).boxed(); inputs .map(new HeavyOperation("A")) .map(new HeavyOperation("B")) .map(new HeavyOperation("C")) .filter(input -> input == 3) .collect(toList());
  • 30. ● Heavy operation - prints to console Streams are lazy class HeavyOperation { public Integer apply(Integer input) { System.out.println("Heavy operation " + operationName + " for element " + input); return input; } }
  • 31. ● Heavy operations on all items Streams are lazy final Stream<Integer> inputs = IntStream.range(0, 10).boxed(); inputs .map(new HeavyOperation("A")) .map(new HeavyOperation("B")) .map(new HeavyOperation("C")) .collect(toList()); Heavy operation A for element 0 Heavy operation B for element 0 Heavy operation C for element 0 Heavy operation A for element 1 Heavy operation B for element 1 Heavy operation C for element 1 Heavy operation A for element 2 Heavy operation B for element 2 Heavy operation C for element 2 Heavy operation A for element 3 Heavy operation B for element 3 Heavy operation C for element 3 Heavy operation A for element 4 Heavy operation B for element 4 Heavy operation C for element 4 Heavy operation A for element 5 Heavy operation B for element 5 Heavy operation C for element 5 Heavy operation A for element 6 Heavy operation B for element 6 Heavy operation C for element 6 Heavy operation A for element 7 Heavy operation B for element 7 Heavy operation C for element 7 Heavy operation A for element 8 Heavy operation B for element 8 Heavy operation C for element 8 Heavy operation A for element 9 Heavy operation B for element 9 Heavy operation C for element 9 CONSOLE OUTPUT
  • 32. ● Only required operations Streams are lazy final Stream<Integer> inputs = IntStream.range(0, 10).boxed(); inputs .map(new HeavyOperation("A")) .map(new HeavyOperation("B")) .map(new HeavyOperation("C")) .filter(input -> input == 3) .findFirst(); Heavy operation A for element 0 Heavy operation B for element 0 Heavy operation C for element 0 Heavy operation A for element 1 Heavy operation B for element 1 Heavy operation C for element 1 Heavy operation A for element 2 Heavy operation B for element 2 Heavy operation C for element 2 Heavy operation A for element 3 Heavy operation B for element 3 Heavy operation C for element 3 CONSOLE OUTPUT
  • 33. ● No collection operation Streams are lazy final Stream<Integer> inputs = IntStream.range(0, 10).boxed(); inputs .map(new HeavyOperation("A")) .map(new HeavyOperation("B")) .map(new HeavyOperation("C")) .filter(input -> input == 3); CONSOLE OUTPUT
  • 34. ● Collection function ● Reduction function (fold function) list .stream() .collect(toList()); Streams - operations output int sum = integers .stream() .sum(); int sum = integers .stream() .reduce(0, (total, item) -> total + item);
  • 35. Streams - parallel execution List inputs = ... inputs .parallelStream() .map(new HeavyOperation("A")) .map(new HeavyOperation("B")) .map(new HeavyOperation("C")) .findFirst();
  • 36. Streams - collectors ● Aggregating ● Comparing ● Grouping List<User> allUsers = users.stream().collect(toList()); User userWithMaxLogins = users.stream() .collect( maxBy( comparing(User::loginsCount) ) ); Map<Role, List<User>> usersPerRole = users.stream() .collect( groupingBy( User::getRole) );
  • 37. Streams - collectors ● Partitioning Map<Boolean, List<User>> activeUsers = stream .collect( partitioningBy( user -> user.getLoginsCount() > 0));
  • 38. Flat mapping ● Stream: Combine stream of streams into single stream. ● Optional: Combine optional of optional into single optional. ○ A pipeline of operations out of which any may fail
  • 39. Flat mapping private Optional<Banana> fetchBananaImperative() { Optional<Island> island = findIsland(); boolean noIslandFound = !island.isPresent(); if (noIslandFound) { return empty(); } Optional<Jungle> jungle = findJungle(island.get()); boolean noJungleFound = !jungle.isPresent(); if (noJungleFound) { return empty(); } Optional<Tree> tree = findTree(jungle.get()); boolean noTreeFound = !tree.isPresent(); if (noTreeFound) { return empty(); } Optional<Banana> banana = findBanana(tree.get()); boolean noBananaFound = !banana.isPresent(); if (noBananaFound) { return empty(); } return banana; }
  • 40. Flat mapping private Optional<Banana> fetchBananaImperative() { Optional<Island> island = findIsland(); boolean noIslandFound = !island.isPresent(); if (noIslandFound) { return empty(); } Optional<Jungle> jungle = findJungle(island.get()); boolean noJungleFound = !jungle.isPresent(); if (noJungleFound) { return empty(); } Optional<Tree> tree = findTree(jungle.get()); boolean noTreeFound = !tree.isPresent(); if (noTreeFound) { return empty(); } Optional<Banana> banana = findBanana(tree.get()); boolean noBananaFound = !banana.isPresent(); if (noBananaFound) { return empty(); } return banana; } private Optional<Banana> fetchBananaFluent() { Optional<Island> islandOptional = findIsland(); Optional<Banana> banana = islandOptional .flatMap(island -> findJungle(island)) .flatMap(jungle -> findTree(jungle)) .flatMap(tree -> findBanana(tree)); return banana; }
  • 41. Map - new methods map.compute(key, (key, value) -> newValue); map.putIfAbsent(key, value); map.replace(key, value); map.replace(key, oldValue, newValue); map.getOrDefault(key, defaultValue); map.merge(key, newValue, (oldValue, newValue) -> mergedValue);
  • 42. Lambda vs method reference Optional<Banana> banana = islandOptional .flatMap(island -> findJungle(island)) .flatMap(jungle -> findTree(jungle)) .flatMap(tree -> findBanana(tree));
  • 43. Lambda vs method reference Optional<Banana> banana = islandOptional .flatMap(island -> findJungle(island)) .flatMap(jungle -> findTree(jungle)) .flatMap(tree -> findBanana(tree)); Optional<Banana> banana = islandOptional .flatMap(island -> findJungle(island)) .flatMap(Jungle::getTree) .flatMap(tree -> tree.getBanana()); ● Syntax may affect readibility
  • 44. Lambda vs method reference Options: ● allow mixing lambda and method reference ● only lambdas Optional<Banana> banana = islandOptional .flatMap(island -> findJungle(island)) .flatMap(Jungle::getTree) .flatMap(tree -> tree.getBanana());