SlideShare a Scribd company logo
1 of 85
Download to read offline
by Mario Fusco 
mario.fusco@gmail.com 
twitter: @mariofusco 
8 in Action 
Lambdas, Streams, and functional-style programming
Project Lambda – A Minimal History 
➢ 2006 – Gosling: "We will never have lambdas in Java" 
➢ 2007 – 3 different proposals for lambdas in Java 
➢ 2008 – Reinhold: "We will never have lambdas in Java" 
➢ 2009 – Start of project Lambda (JSR 335) 
public boolean willJavaHaveLambdas() { 
return currentYear % 2 == 1; 
}
From Single Method Interfaces … 
public interface Comparator<T> { 
int compare(T o1, T o2); 
Functional 
Interface 
} 
Collections.sort(strings, new Comparator<String>() { 
public int compare(String s1, String s2) { 
return s1.compareToIgnoreCase(s2); 
} 
}); 
➢ Bulky syntax 
➢ Confusion surrounding the meaning of names and this 
➢ Inability to capture non-final local variables 
➢ Inability to abstract over control flow
… To Lambda Expressions 
Collections.sort(strings,(s1, s2) -> s1.compareToIgnoreCase(s2)); 
Lambda expression are always converted to 
instance of a functional interface 
Comparator<String> c = (s1, s2) -> s1.compareToIgnoreCase(s2); 
Compiler figures out the types 
No need of changing the JVM to create a new 
type for lambda expressions
Common JDK8 @FunctionalInterfaces 
➢ Predicate<T> → test a property of the object passed as argument 
➢ Consumer<T> → execute an action on the object passed as argument 
➢ Function<T, U> → transform a T to a U 
➢ BiFunction<T, U, V> → transform a (T, U) to a V 
➢ Supplier<T> → provide an instance of a T (such as a factory) 
➢ UnaryOperator<T> → a unary operator from T -> T 
➢ BinaryOperator<T> → a binary operator from (T, T) -> T 
Give a look at java.util.function.*
Anatomy of a lambda expression 
A lambda expression is like an (anonymous) method: 
it provides a list of formal parameters and a body 
s -> s.length() 
(int x, int y) -> x + y 
() -> 42 
(x, y, z) -> { 
if (x) { 
return y; 
} else { 
return z; 
} 
} 
The formal parameters of 
a lambda expression may 
have either inferred or 
declared types 
Return is implicit and 
can be omitted 
A lambda body is either a 
single expression or a block
However … 
… syntax is probably the less important 
thing about lambda expression … 
… the really fundamental thing about 
lambda expression is … 
… the huge paradigm shift they imply
Why Lambdas? 
➢ Behaviors can be passed to a method together with data 
➢ API designers can build more powerful, expressive APIs 
➢ More room for generalization 
➢ Pass behaviors to a method together with normal data 
➢ Libraries remain in control of computation 
➢ e.g. internal vs. external iteration 
➢ More opportunities for optimization 
➢ Laziness 
➢ Parallelism 
➢ Out-of-order execution 
➢ More regular and then more readable code 
➢ e.g. nested loops vs. pipelined (fluent) operations 
➢ Better composability and reusability
Example 1 
Your first Lambda
Internal vs External Iteration
Internal vs External Iteration 
for (Employee e : employees) { 
e.setSalary(e.getSalary() * 1.03); 
} 
Ěś Inherently serial 
Ěś Client has to manage iteration 
Ěś Nested loops are poorly readable 
employees.forEach(e -> e.setSalary(e.getSalary() * 1.03)); 
Not only a syntactic change! 
+ Library is in control → opportunity for internal optimizations as parallelization, 
lazy evaluation, out-of-order execution 
+ More what, less how → better readability 
+ Fluent (pipelined) operations → better readability 
+ Client can pass behaviors into the API as data → 
possibility to abstract and generalize over behavior → 
more powerful, expressive APIs
Sorting with Lambdas 
Comparator<Person> byAge = new Comparator<Person>() { 
public int compare(Person p1, Person p2) { 
return p1.getAge() – p2.getAge(); 
} 
}; 
Collections.sort(people, byAge); 
Functional interface 
Lambda expression 
Comparator<Person> byAge = (p1, p2) -> p1.getAge() – p2.getAge(); 
Collections.sort(people, (p1, p2) -> p1.getAge() – p2.getAge());
Can We Do Better? 
Comparator<Person> byAge = Comparators.comparing(p -> p.getAge()); 
Comparator<Person> byAge = Comparators.comparing(Person::getAge); 
Method reference 
Readability 
Collections.sort(people, comparing(Person::getAge)); 
Collections.sort(people, comparing(Person::getAge).reverse()); 
Collections.sort(people, comparing(Person::getAge) 
.compose(comparing(Person::getName))); 
Reusability 
Composability
Example 2 
Passing behavior 
with Lambda
OOP vs FP 
OOP makes code understandable 
by encapsulating moving parts 
FP makes code understandable 
by minimizing moving parts 
- Michael Feathers
The OOP/FP dualism - OOP 
public class Bird { } 
public class Cat { 
private Bird catch; 
private boolean full; 
public void capture(Bird bird) { 
catch = bird; 
} 
public void eat() { 
full = true; 
catch = null; 
} 
} 
Cat cat = new Cat(); 
Bird bird = new Bird(); 
cat.capture(bird); 
cat.eat(); 
The story
The OOP/FP dualism - FP 
public class Bird { } 
public class Cat { 
public CatWithCatch capture(Bird bird) { return new CatWithCatch(bird); } 
} 
public class CatWithCatch { 
private final Bird catch; 
public CatWithCatch(Bird bird) { catch = bird; } 
public FullCat eat() { return new FullCat(); } 
} 
public class FullCat { } 
BiFunction<Cat, Bird, FullCat> story = 
((BiFunction<Cat, Bird, CatWithCatch>)Cat::capture) 
.compose(CatWithCatch::eat); 
FullCat fullCat = story.apply( new Cat(), new Bird() ); 
Immutability 
Emphasis on verbs 
instead of names 
No need to test internal state: correctness enforced by the compiler
Streams - Efficiency with laziness 
List<Employee> employess = ... 
employees.stream() 
.filter(e -> e.getIncome() > 50000) 
.map(e -> e.getName()) 
.forEach(System.out::println); 
Represents a sequence of element from a source 
Not a data structure: doesn't store elements but compute them on demand 
Sources can be Collection, array, generating function, I/O .... 
Encourages a pipelined ( "fluent" ) usage style 
Operations are divided between intermediate and terminal 
Lazy in nature: only terminal operations actually trigger a computation
Evolving APIs with default methods 
Where does that stream() method come from? 
public interface Collection<E> extends Iterable<E> { 
... 
default Stream<E> stream() { 
return StreamSupport.stream(spliterator(), false); 
} 
} 
✔ Multiple inheritance of type since Java 1.0 
✔ Java 8 introduces multiple inheritance of behavior 
✔ No multiple inheritance of state (like in Scala's traits)
Default methods resolution rules 
1.Classes always win: a method declaration in the class or a 
superclass takes priority over any default method declaration. 
2.Then sub-interfaces win: the method with the same signature in 
the most specific default-providing interface is selected. 
3.If the choice is still ambiguous, the class inheriting from multiple 
interfaces has to explicitly select which default method 
implementation to use by overriding it and calling the desired 
method explicitly. 
public interface A { 
default void hello() { System.out.println("Hello from A"); } 
} public interface B { 
default void hello() { System.out.println("Hello from B"); } 
} public class C implements B, A { 
void hello() { B.super.hello(); } 
}
Example 3 
Stream laziness
Intermediate & Terminal Operations 
Return the final result of 
the operation pipeline 
Intermediate 
distinct 
map, flatMap 
limit, skip 
peek 
sorted 
Terminal 
collect 
count 
forEach 
min, max 
reduce 
toArray 
findAny, findFirst 
allMatch, 
anyMatch, 
noneMatch 
Return another Stream and 
then can be chained to form 
a pipeline of operations
map : an intermediate operation 
map( -> ) 
Stream
reduce : a terminal operation 
Stream 
Integer 
reduce(0, (a, b) -> a + b)
Putting them all together 
List<String> strings = asList("Lambda", "expressions", "are", 
"easy", "and", "useful"); 
int totalLength = strings.stream() 
.map(String::length) 
.reduce(0, (a, b) -> a + b);
Stream Operations Pipelining 
Intermediate Operations are lazy and return another 
Stream allowing to fluently pipeline other operations 
Terminal Operations are eager and computes the result of 
the whole pipeline
Example 4 
Prime numbers
Separation of Concerns 
List<String> errors = new ArrayList<>(); 
int errorCount = 0; 
File file = new File(fileName); 
String line = file.readLine(); 
while (errorCount < 40 && line != null) { 
if (line.startsWith("ERROR")) { 
errors.add(line); 
errorCount++; 
} 
line = file.readLine(); 
List<String> errors = 
Files.lines(Paths.get(fileName)) 
.filter(l -> l.startsWith("ERROR") 
.limit(40) 
.collect(toList()); 
}
Example 5 
Stream from a File
Grouping 
Map<Dish.Type, List<Dish>> dishesByType = new HashMap<>(); 
for (Dish dish : menu) { 
Dish.Type type = dish.getType(); 
List<Dish> dishes = dishesByType.get(type); 
if (dishes == null) { 
dishes = new ArrayList<>(); 
dishesByType.put(type, dishes); 
} 
dishes.add(dish); 
}
Grouping with Collectors 
apply key 
classify item into list 
next 
item 
grouping Map 
fish meat other 
salmon pizza 
rice 
french fries 
pork 
beef 
chicken 
prawns 
Classification 
Function fish 
Stream 
Map<Dish.Type, List<Dish>> dishesByType = 
menu.stream() 
.collect(groupingBy(Dish::getType));
Example 6 
Grouping
groupingBy 
Stream 
Dish::getType 
classification 
function 
Complex Grouping 
subStream subStream subStream 
collectingAndThen 
reducing 
result 
Optional[pork] 
Optional::get 
result 
grouping Map 
collectingAndThen 
fish meat other 
salmon 
pork pizza 
reducing 
collectingAndThen 
reducing 
result result 
The original Stream is 
divided in subStreams 
according to the 
classification function 
Each subStreams is 
independently 
processed by the 
second Collector 
transformation 
function 
The reducing Collector 
returns the most caloric Dish 
wrapped in an Optional 
The collectingAndThen Collector 
returns the value extracted from 
the former Optional 
The results of the 2nd 
level Collectors 
become the values of 
the grouping map
Streams – Parallelism for free 
parallelStream() 
employees.stream() 
.filter(e -> e.getRole() == Role.MANAGER) 
.map(Employee::getIncome) 
.reduce(0, (a, b) -> a + b);
A parallel reduction
Example 7 
Parallel Streams
Is there such thing as a free lunch?
Probably yes … 
… but we need functional 
forks and knives to eat it
Concurrency & Parallelism 
Parallel programming 
Running multiple tasks at 
the same time 
Concurrent programming 
Managing concurrent requests 
Both are hard!
The cause of the problem … 
Mutable state + 
Parallel processing = 
Non-determinism 
Functional 
Programming
Race conditions 
Deadlocks 
Starvation 
Livelocks 
… and its effects 
Too hard to think about them!
The native Java concurrency model 
Based on: 
Locks Synchronization 
They are sometimes plain evil … 
Threads 
Semaphores 
… and sometimes a necessary pain … 
… but always the wrong default
Different concurrency models 
Isolated mutable state (actors) 
Purely immutable (pure functions) 
Shared mutable state 
(threads + locks)
Summing attendants ages (Threads) 
class Blackboard { 
int sum = 0; 
int read() { return sum; } 
void write(int value) { sum = value; } 
} 
class Attendant implements Runnable { 
int age; 
Blackboard blackboard; 
public void run() { 
synchronized(blackboard) { 
int oldSum = blackboard.read(); 
int newSum = oldSum + age; 
blackboard.write(newSum); 
} 
} 
}
Summing attendants ages (Actors) 
class Blackboard extends UntypedActors { 
int sum = 0; 
public void onReceive(Object message) { 
if (message instanceof Integer) { 
sum += (Integer)message; 
} 
} 
} 
class Attendant { 
int age; 
Blackboard blackboard; 
public void sendAge() { 
blackboard.sendOneWay(age); 
} 
}
Summing attendants ages (Functional) 
class Blackboard { 
final int sum; 
Blackboard(int sum) { this.sum = sum; } 
} 
class Attendant { 
int age; 
Attendant next; 
public Blackboard addMyAge(Blackboard blackboard) { 
final Blackboard b = new Blackboard(blackboard.sum + age); 
return next == null ? b : next.myAge(b); 
} 
}
The state quadrants 
Mutable 
Immutable 
Shared 
Unshared 
Actors 
Threads 
Functional 
Programming 
Determinism 
Non-determinism
What is a functional program? 
A program created using only pure functions 
No side effects allowed like: 
} 
}avoidable 
Reassigning a variable 
Modifying a data structure in place 
Setting a field on an object 
Throwing an exception or halting with an error 
Printing to the console 
Reading user input 
Reading from or writing to a file 
Drawing on the screen 
deferrable 
Functional programming is a restriction on how we write 
programs, but not on what they can do
Example 8 
Modularity to 
confine side-effects
A pure functional core 
functional 
core 
a thin external layer to handle side-effects 
Any function with side-effects can be split into a pure function at the 
core and a pair of functions with side-effect. This transformation can 
be repeated to push side-effects to the outer layers of the program.
What is a (pure) function? 
A function with input type A and output type B 
is a computation which relates every value a of 
type A to exactly one value b of type B such 
that b is determined solely by the value of a 
But, if it really is a 
function, it will do 
nothing else
Referential transparency 
An expression e is referentially transparent if for all programs p, 
all occurrences of e in p can be replaced by the result of 
evaluating e, without affecting the observable behavior of p 
A function f is pure if the expression f(x) is referentially 
transparent for all referentially transparent x
RT 
String x = "purple"; 
String r1 = x.replace('p', 't'); 
String r2 = x.replace('p', 't'); 
String r1 = "purple".replace('p', 't'); 
r1: "turtle" 
String r2 = "purple".replace('p', 't'); 
r2: "turtle" 
Non-RT 
StringBuilder x = new StringBuilder("Hi"); 
StringBuilder y = x.append(", mom"); 
String r1 = y.toString(); 
String r2 = y.toString(); 
String r1 = x.append(", mom").toString(); 
r1: "Hi, mom" 
String r2 = x.append(", mom").toString(); 
r1: "Hi, mom, mom" 
vs.
RT wins 
Under a developer point of view: 
Easier to reason about since effects of evaluation are purely 
local 
Use of the substitution model: it's possible to replace a term 
with an equivalent one 
Under a performance point of view: 
The JVM is free to optimize the code by safely reordering the 
instructions 
No need to synchronize access to shared data 
Possible to cache the result of time consuming functions 
(memoization), e.g. with 
Map.computeIfAbsent(K key, 
Function<? super K,? extends V> mappingFunction)
Mutability 
Parameter binding is about assigning names to things 
Mutating variables is about assigning things to names 
Does that second 
one sound weird? 
… well it's because 
it IS weird
Immutability 
Immutable objects can be shared among 
many threads exactly because none of 
them can modify it 
In the same way immutable (persistent) 
data structures can be shared without any 
need to synchronize the different threads 
accessing them
Old Root 
New Root 
5 
8 
7 9 
3 
4 
E E E E E E 
E 
5 
3 
2 
E E 
Persistent Collections 
Shared data
Example 9 
Avoiding mutability
NullPointerException 
Raise your hand if 
you've ever seen this
Null references? No, Thanks 
✗ Errors source → NPE is by far the most common exception in Java 
✗ Bloatware source → Worsen readability by making necessary to fill our code 
with null checks 
✗ Meaningless → Don't have any semantic meaning and in particular are the 
wrong way to model the absence of a value in a statically typed language 
✗ Breaks Java philosophy → Java always hides pointers to developers, except 
in one case: the null pointer 
✗ A hole in the type system → Null has the bottom type, meaning that it can 
be assigned to any reference type: this is a problem because, when 
propagated to another part of the system, you have no idea what that null 
was initially supposed to be 
Tony Hoare, who invented the null reference in 1965 while working on 
an object oriented language called ALGOL W, called its invention his 
“billion dollar mistake”
Replacing nulls with Optionals 
If nulls are so problematic why don't we just avoid them? 
Optional 
value 
value 
Optional 
EMPTY 
null 
Optional is a type that models a possibly missing value
public class Person { 
private Car car; 
public Car getCar() { return car; } 
} 
public class Car { 
private Insurance insurance; 
public Insurance getInsurance() { return insurance; } 
} 
public class Insurance { 
private String name; 
public String getName() { return name; } 
} 
Finding Car's Insurance Name
String getCarInsuranceName(Person person) { 
if (person != null) { 
Car car = person.getCar(); 
if (car != null) { 
Insurance insurance = car.getInsurance(); 
if (insurance != null) { 
return insurance.getName() 
} 
} 
} 
return "Unknown"; 
} 
Attempt 1: deep doubts
Attempt 2: too many choices 
String getCarInsuranceName(Person person) { 
if (person == null) { 
return "Unknown"; 
} 
Car car = person.getCar(); 
if (car == null) { 
return "Unknown"; 
} 
Insurance insurance = car.getInsurance(); 
if (insurance == null) { 
return "Unknown"; 
} 
return insurance.getName() 
}
Optional to the rescue 
public class Optional<T> { 
private static final Optional<?> EMPTY = new Optional<>(null); 
private final T value; 
private Optional(T value) { 
this.value = value; 
} 
public<U> Optional<U> map(Function<? super T, ? extends U> f) { 
return value == null ? EMPTY : new Optional(f.apply(value)); 
} 
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> f) { 
return value == null ? EMPTY : f.apply(value); 
} 
}
public class Person { 
private Optional<Car> car; 
public Optional<Car> getCar() { return car; } 
} 
public class Car { 
private Optional<Insurance> insurance; 
public Optional<Insurance> getInsurance() { return insurance; } 
} 
public class Insurance { 
private String name; 
public String getName() { return name; } 
} 
Rethinking our model 
Using the type system 
to model nullable value
String getCarInsuranceName(Optional<Person> person) { 
return person.flatMap(person -> person.getCar()) 
.flatMap(car -> car.getInsurance()) 
.map(insurance -> insurance.getName()) 
.orElse("Unknown"); 
} 
Restoring the sanity
String getCarInsuranceName(Optional<Person> person) { 
return person.flatMap(person -> person.getCar()) 
.flatMap(car -> car.getInsurance()) 
.map(insurance -> insurance.getName()) 
.orElse("Unknown"); 
} 
Restoring the sanity 
Optional 
Person
String getCarInsuranceName(Optional<Person> person) { 
return person.flatMap(person -> person.getCar()) 
.flatMap(car -> car.getInsurance()) 
.map(insurance -> insurance.getName()) 
.orElse("Unknown"); 
} 
Restoring the sanity 
Optional 
Person 
flatMap(person -> person.getCar())
String getCarInsuranceName(Optional<Person> person) { 
return person.flatMap(person -> person.getCar()) 
.flatMap(car -> car.getInsurance()) 
.map(insurance -> insurance.getName()) 
.orElse("Unknown"); 
} 
Restoring the sanity 
Optional 
flatMap(person -> person.getCar()) 
Optional 
Car
String getCarInsuranceName(Optional<Person> person) { 
return person.flatMap(person -> person.getCar()) 
.flatMap(car -> car.getInsurance()) 
.map(insurance -> insurance.getName()) 
.orElse("Unknown"); 
} 
Restoring the sanity 
Optional 
flatMap(car -> car.getInsurance()) 
Car
String getCarInsuranceName(Optional<Person> person) { 
return person.flatMap(person -> person.getCar()) 
.flatMap(car -> car.getInsurance()) 
.map(insurance -> insurance.getName()) 
.orElse("Unknown"); 
} 
Restoring the sanity 
Optional 
flatMap(car -> car.getInsurance()) 
Optional 
Insurance
String getCarInsuranceName(Optional<Person> person) { 
return person.flatMap(person -> person.getCar()) 
.flatMap(car -> car.getInsurance()) 
.map(insurance -> insurance.getName()) 
.orElse("Unknown"); 
} 
Restoring the sanity 
Optional 
map(insurance -> insurance.getName()) 
Insurance
String getCarInsuranceName(Optional<Person> person) { 
return person.flatMap(person -> person.getCar()) 
.flatMap(car -> car.getInsurance()) 
.map(insurance -> insurance.getName()) 
.orElse("Unknown"); 
} 
Restoring the sanity 
Optional 
orElse("Unknown") 
String
Example 10 
Using Optional
Thinking in Functions 
Learning a new language is relatively easy 
compared with learning a new paradigm. 
Functional Programming is more a new way of 
thinking than a new tool set
Example 11 
The Loan Pattern
Example 12 
Conditional deferred 
execution
Futures, weren't they enough? 
The Future interface was introduced in Java 5 to model an 
asynchronous computation and then provide an handle to a result 
that will be made available at some point in the future. 
But it doesn't allow to: 
✗ Combining two asynchronous 
computations in one 
✗ Waiting for the completion of all 
tasks performed by a set of Futures 
✗ Waiting for the completion of only 
the quickest task in a set of Futures 
(possibly because they’re trying to 
calculate the same value in different 
ways) and retrieving its result 
✗ Programmatically completing a 
Future 
✗ Reacting to a Future completion
CompletableFutures to the rescue 
✔ Programmatically completing a Future with a result … 
boolean complete(T value) 
… or an error 
boolean completeExceptionally(Throwable ex) 
✔ Reacting to Future completion 
CompletableFuture<Void> thenAccept(Consumer<? super T> action) 
✔ Combining 2 async operation in sequence ... 
static CompletableFuture<U> thenCompose( 
Function<? super T,? extends CompletionStage<U>> fn) 
… or in parallel 
static CompletableFuture<V> thenCombine( 
CompletionStage<? extends U> other, 
BiFunction<? super T,? super U,? extends V> fn) 
✔ Waiting for the completion of all Futures ... 
static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs) 
… or only the fastest one 
static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)
Example 13 
Putting CompletableFutures 
at work
Key Takeaways 
Think in functions 
Strive for immutability 
Confine side-effects 
Avoid blocking code 
Cede control with higher-order functions 
Leverage referential transparency 
Use FP to design more composable and reusable API 
Model potentially missing values with Optionals 
… but there are no dogmas 
Be pragmatic and use the right tool for the job at hand 
Poly-paradigm programming is more powerful 
and effective than polyglot programming
The bottom line 
Java is getting functional 
EMBRACE IT!
Thanks … Questions? 
Q A 
Mario Fusco 
Red Hat – Senior Software Engineer 
mario.fusco@gmail.com 
twitter: @mariofusco 
code examples @ https://github.com/mariofusco/Java8WS

More Related Content

What's hot

jQuery Effects
jQuery EffectsjQuery Effects
jQuery Effects
Adelon Zeta
 
Java programming-examples
Java programming-examplesJava programming-examples
Java programming-examples
Mumbai Academisc
 
Optional in Java 8
Optional in Java 8Optional in Java 8
Optional in Java 8
Richard Walker
 
Collections In Java
Collections In JavaCollections In Java
Collections In Java
Binoj T E
 

What's hot (20)

Introduction to java 8 stream api
Introduction to java 8 stream apiIntroduction to java 8 stream api
Introduction to java 8 stream api
 
3. Java Script
3. Java Script3. Java Script
3. Java Script
 
Map(), flatmap() and reduce() are your new best friends: simpler collections,...
Map(), flatmap() and reduce() are your new best friends: simpler collections,...Map(), flatmap() and reduce() are your new best friends: simpler collections,...
Map(), flatmap() and reduce() are your new best friends: simpler collections,...
 
Java - Generic programming
Java - Generic programmingJava - Generic programming
Java - Generic programming
 
Core java concepts
Core java  conceptsCore java  concepts
Core java concepts
 
jQuery Effects
jQuery EffectsjQuery Effects
jQuery Effects
 
Typescript ppt
Typescript pptTypescript ppt
Typescript ppt
 
React hooks
React hooksReact hooks
React hooks
 
java 8 new features
java 8 new features java 8 new features
java 8 new features
 
Clean coding-practices
Clean coding-practicesClean coding-practices
Clean coding-practices
 
Basics of React Hooks.pptx.pdf
Basics of React Hooks.pptx.pdfBasics of React Hooks.pptx.pdf
Basics of React Hooks.pptx.pdf
 
Clean code
Clean codeClean code
Clean code
 
Java programming-examples
Java programming-examplesJava programming-examples
Java programming-examples
 
Optional in Java 8
Optional in Java 8Optional in Java 8
Optional in Java 8
 
Collections In Java
Collections In JavaCollections In Java
Collections In Java
 
Java 8 Stream API. A different way to process collections.
Java 8 Stream API. A different way to process collections.Java 8 Stream API. A different way to process collections.
Java 8 Stream API. A different way to process collections.
 
Workshop 21: React Router
Workshop 21: React RouterWorkshop 21: React Router
Workshop 21: React Router
 
Generics in java
Generics in javaGenerics in java
Generics in java
 
Java Collections
Java  Collections Java  Collections
Java Collections
 
Le Wagon - React 101
Le Wagon - React 101Le Wagon - React 101
Le Wagon - React 101
 

Viewers also liked

FP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyondFP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyond
Mario Fusco
 
No more loops with lambdaj
No more loops with lambdajNo more loops with lambdaj
No more loops with lambdaj
Mario Fusco
 
If You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are WrongIf You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are Wrong
Mario Fusco
 
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Mario Fusco
 
Scala - where objects and functions meet
Scala - where objects and functions meetScala - where objects and functions meet
Scala - where objects and functions meet
Mario Fusco
 
Why we cannot ignore Functional Programming
Why we cannot ignore Functional ProgrammingWhy we cannot ignore Functional Programming
Why we cannot ignore Functional Programming
Mario Fusco
 
Real world DSL - making technical and business people speaking the same language
Real world DSL - making technical and business people speaking the same languageReal world DSL - making technical and business people speaking the same language
Real world DSL - making technical and business people speaking the same language
Mario Fusco
 
Taxonomy of Scala
Taxonomy of ScalaTaxonomy of Scala
Taxonomy of Scala
shinolajla
 

Viewers also liked (20)

FP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyondFP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyond
 
No more loops with lambdaj
No more loops with lambdajNo more loops with lambdaj
No more loops with lambdaj
 
OOP and FP - Become a Better Programmer
OOP and FP - Become a Better ProgrammerOOP and FP - Become a Better Programmer
OOP and FP - Become a Better Programmer
 
Reactive Programming for a demanding world: building event-driven and respons...
Reactive Programming for a demanding world: building event-driven and respons...Reactive Programming for a demanding world: building event-driven and respons...
Reactive Programming for a demanding world: building event-driven and respons...
 
If You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are WrongIf You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are Wrong
 
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...
 
Comparing different concurrency models on the JVM
Comparing different concurrency models on the JVMComparing different concurrency models on the JVM
Comparing different concurrency models on the JVM
 
Hammurabi
HammurabiHammurabi
Hammurabi
 
Scala - where objects and functions meet
Scala - where objects and functions meetScala - where objects and functions meet
Scala - where objects and functions meet
 
Why we cannot ignore Functional Programming
Why we cannot ignore Functional ProgrammingWhy we cannot ignore Functional Programming
Why we cannot ignore Functional Programming
 
Real world DSL - making technical and business people speaking the same language
Real world DSL - making technical and business people speaking the same languageReal world DSL - making technical and business people speaking the same language
Real world DSL - making technical and business people speaking the same language
 
Drools 6 deep dive
Drools 6 deep diveDrools 6 deep dive
Drools 6 deep dive
 
Functional programming with Java 8
Functional programming with Java 8Functional programming with Java 8
Functional programming with Java 8
 
55 New Features in Java SE 8
55 New Features in Java SE 855 New Features in Java SE 8
55 New Features in Java SE 8
 
Functional programming in Java 8 - workshop at flatMap Oslo 2014
Functional programming in Java 8 - workshop at flatMap Oslo 2014Functional programming in Java 8 - workshop at flatMap Oslo 2014
Functional programming in Java 8 - workshop at flatMap Oslo 2014
 
Java 8 ​and ​Best Practices
Java 8 ​and ​Best PracticesJava 8 ​and ​Best Practices
Java 8 ​and ​Best Practices
 
Java 8 - Nuevas caracterĂ­sticas
Java 8 - Nuevas caracterĂ­sticasJava 8 - Nuevas caracterĂ­sticas
Java 8 - Nuevas caracterĂ­sticas
 
Taxonomy of Scala
Taxonomy of ScalaTaxonomy of Scala
Taxonomy of Scala
 
Hanoi jug java 8 stream api
Hanoi jug   java 8 stream apiHanoi jug   java 8 stream api
Hanoi jug java 8 stream api
 
NixCon Berlin 2015 - Nix at LogicBlox
NixCon Berlin 2015 - Nix at LogicBloxNixCon Berlin 2015 - Nix at LogicBlox
NixCon Berlin 2015 - Nix at LogicBlox
 

Similar to Java 8 Workshop

Similar to Java 8 Workshop (20)

Java gets a closure
Java gets a closureJava gets a closure
Java gets a closure
 
Java 8 presentation
Java 8 presentationJava 8 presentation
Java 8 presentation
 
JavaOne 2016 - Learn Lambda and functional programming
JavaOne 2016 - Learn Lambda and functional programmingJavaOne 2016 - Learn Lambda and functional programming
JavaOne 2016 - Learn Lambda and functional programming
 
Wien15 java8
Wien15 java8Wien15 java8
Wien15 java8
 
Java8
Java8Java8
Java8
 
What is new in Java 8
What is new in Java 8What is new in Java 8
What is new in Java 8
 
Major Java 8 features
Major Java 8 featuresMajor Java 8 features
Major Java 8 features
 
documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...
documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...
documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...
 
Productive Programming in Java 8 - with Lambdas and Streams
Productive Programming in Java 8 - with Lambdas and Streams Productive Programming in Java 8 - with Lambdas and Streams
Productive Programming in Java 8 - with Lambdas and Streams
 
Java 8 Intro - Core Features
Java 8 Intro - Core FeaturesJava 8 Intro - Core Features
Java 8 Intro - Core Features
 
Java 8 by example!
Java 8 by example!Java 8 by example!
Java 8 by example!
 
SOLID mit Java 8
SOLID mit Java 8SOLID mit Java 8
SOLID mit Java 8
 
Lambda Functions in Java 8
Lambda Functions in Java 8Lambda Functions in Java 8
Lambda Functions in Java 8
 
Java 8 new features or the ones you might actually use
Java 8 new features or the ones you might actually useJava 8 new features or the ones you might actually use
Java 8 new features or the ones you might actually use
 
java150929145120-lva1-app6892 (2).pptx
java150929145120-lva1-app6892 (2).pptxjava150929145120-lva1-app6892 (2).pptx
java150929145120-lva1-app6892 (2).pptx
 
Java 8
Java 8Java 8
Java 8
 
Java8
Java8Java8
Java8
 
The... Wonderful? World of Lambdas
The... Wonderful? World of LambdasThe... Wonderful? World of Lambdas
The... Wonderful? World of Lambdas
 
Java 8 new features
Java 8 new featuresJava 8 new features
Java 8 new features
 
Thumbtack Expertise Days # 5 - Javaz
Thumbtack Expertise Days # 5 - JavazThumbtack Expertise Days # 5 - Javaz
Thumbtack Expertise Days # 5 - Javaz
 

More from Mario Fusco

Introducing Drools
Introducing DroolsIntroducing Drools
Introducing Drools
Mario Fusco
 
Java 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forwardJava 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forward
Mario Fusco
 
Swiss army knife Spring
Swiss army knife SpringSwiss army knife Spring
Swiss army knife Spring
Mario Fusco
 
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STMConcurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Mario Fusco
 

More from Mario Fusco (8)

Kogito: cloud native business automation
Kogito: cloud native business automationKogito: cloud native business automation
Kogito: cloud native business automation
 
Let's make a contract: the art of designing a Java API
Let's make a contract: the art of designing a Java APILet's make a contract: the art of designing a Java API
Let's make a contract: the art of designing a Java API
 
How and why I turned my old Java projects into a first-class serverless compo...
How and why I turned my old Java projects into a first-class serverless compo...How and why I turned my old Java projects into a first-class serverless compo...
How and why I turned my old Java projects into a first-class serverless compo...
 
OOP and FP
OOP and FPOOP and FP
OOP and FP
 
Introducing Drools
Introducing DroolsIntroducing Drools
Introducing Drools
 
Java 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forwardJava 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forward
 
Swiss army knife Spring
Swiss army knife SpringSwiss army knife Spring
Swiss army knife Spring
 
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STMConcurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
 

Recently uploaded

Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Bert Jan Schrijver
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
VictorSzoltysek
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
masabamasaba
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
masabamasaba
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
shinachiaurasa2
 

Recently uploaded (20)

Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 

Java 8 Workshop

  • 1. by Mario Fusco mario.fusco@gmail.com twitter: @mariofusco 8 in Action Lambdas, Streams, and functional-style programming
  • 2. Project Lambda – A Minimal History ➢ 2006 – Gosling: "We will never have lambdas in Java" ➢ 2007 – 3 different proposals for lambdas in Java ➢ 2008 – Reinhold: "We will never have lambdas in Java" ➢ 2009 – Start of project Lambda (JSR 335) public boolean willJavaHaveLambdas() { return currentYear % 2 == 1; }
  • 3. From Single Method Interfaces … public interface Comparator<T> { int compare(T o1, T o2); Functional Interface } Collections.sort(strings, new Comparator<String>() { public int compare(String s1, String s2) { return s1.compareToIgnoreCase(s2); } }); ➢ Bulky syntax ➢ Confusion surrounding the meaning of names and this ➢ Inability to capture non-final local variables ➢ Inability to abstract over control flow
  • 4. … To Lambda Expressions Collections.sort(strings,(s1, s2) -> s1.compareToIgnoreCase(s2)); Lambda expression are always converted to instance of a functional interface Comparator<String> c = (s1, s2) -> s1.compareToIgnoreCase(s2); Compiler figures out the types No need of changing the JVM to create a new type for lambda expressions
  • 5. Common JDK8 @FunctionalInterfaces ➢ Predicate<T> → test a property of the object passed as argument ➢ Consumer<T> → execute an action on the object passed as argument ➢ Function<T, U> → transform a T to a U ➢ BiFunction<T, U, V> → transform a (T, U) to a V ➢ Supplier<T> → provide an instance of a T (such as a factory) ➢ UnaryOperator<T> → a unary operator from T -> T ➢ BinaryOperator<T> → a binary operator from (T, T) -> T Give a look at java.util.function.*
  • 6. Anatomy of a lambda expression A lambda expression is like an (anonymous) method: it provides a list of formal parameters and a body s -> s.length() (int x, int y) -> x + y () -> 42 (x, y, z) -> { if (x) { return y; } else { return z; } } The formal parameters of a lambda expression may have either inferred or declared types Return is implicit and can be omitted A lambda body is either a single expression or a block
  • 7. However … … syntax is probably the less important thing about lambda expression … … the really fundamental thing about lambda expression is … … the huge paradigm shift they imply
  • 8. Why Lambdas? ➢ Behaviors can be passed to a method together with data ➢ API designers can build more powerful, expressive APIs ➢ More room for generalization ➢ Pass behaviors to a method together with normal data ➢ Libraries remain in control of computation ➢ e.g. internal vs. external iteration ➢ More opportunities for optimization ➢ Laziness ➢ Parallelism ➢ Out-of-order execution ➢ More regular and then more readable code ➢ e.g. nested loops vs. pipelined (fluent) operations ➢ Better composability and reusability
  • 9. Example 1 Your first Lambda
  • 10. Internal vs External Iteration
  • 11. Internal vs External Iteration for (Employee e : employees) { e.setSalary(e.getSalary() * 1.03); } Ěś Inherently serial Ěś Client has to manage iteration Ěś Nested loops are poorly readable employees.forEach(e -> e.setSalary(e.getSalary() * 1.03)); Not only a syntactic change! + Library is in control → opportunity for internal optimizations as parallelization, lazy evaluation, out-of-order execution + More what, less how → better readability + Fluent (pipelined) operations → better readability + Client can pass behaviors into the API as data → possibility to abstract and generalize over behavior → more powerful, expressive APIs
  • 12. Sorting with Lambdas Comparator<Person> byAge = new Comparator<Person>() { public int compare(Person p1, Person p2) { return p1.getAge() – p2.getAge(); } }; Collections.sort(people, byAge); Functional interface Lambda expression Comparator<Person> byAge = (p1, p2) -> p1.getAge() – p2.getAge(); Collections.sort(people, (p1, p2) -> p1.getAge() – p2.getAge());
  • 13. Can We Do Better? Comparator<Person> byAge = Comparators.comparing(p -> p.getAge()); Comparator<Person> byAge = Comparators.comparing(Person::getAge); Method reference Readability Collections.sort(people, comparing(Person::getAge)); Collections.sort(people, comparing(Person::getAge).reverse()); Collections.sort(people, comparing(Person::getAge) .compose(comparing(Person::getName))); Reusability Composability
  • 14. Example 2 Passing behavior with Lambda
  • 15. OOP vs FP OOP makes code understandable by encapsulating moving parts FP makes code understandable by minimizing moving parts - Michael Feathers
  • 16. The OOP/FP dualism - OOP public class Bird { } public class Cat { private Bird catch; private boolean full; public void capture(Bird bird) { catch = bird; } public void eat() { full = true; catch = null; } } Cat cat = new Cat(); Bird bird = new Bird(); cat.capture(bird); cat.eat(); The story
  • 17. The OOP/FP dualism - FP public class Bird { } public class Cat { public CatWithCatch capture(Bird bird) { return new CatWithCatch(bird); } } public class CatWithCatch { private final Bird catch; public CatWithCatch(Bird bird) { catch = bird; } public FullCat eat() { return new FullCat(); } } public class FullCat { } BiFunction<Cat, Bird, FullCat> story = ((BiFunction<Cat, Bird, CatWithCatch>)Cat::capture) .compose(CatWithCatch::eat); FullCat fullCat = story.apply( new Cat(), new Bird() ); Immutability Emphasis on verbs instead of names No need to test internal state: correctness enforced by the compiler
  • 18. Streams - Efficiency with laziness List<Employee> employess = ... employees.stream() .filter(e -> e.getIncome() > 50000) .map(e -> e.getName()) .forEach(System.out::println); Represents a sequence of element from a source Not a data structure: doesn't store elements but compute them on demand Sources can be Collection, array, generating function, I/O .... Encourages a pipelined ( "fluent" ) usage style Operations are divided between intermediate and terminal Lazy in nature: only terminal operations actually trigger a computation
  • 19. Evolving APIs with default methods Where does that stream() method come from? public interface Collection<E> extends Iterable<E> { ... default Stream<E> stream() { return StreamSupport.stream(spliterator(), false); } } ✔ Multiple inheritance of type since Java 1.0 ✔ Java 8 introduces multiple inheritance of behavior ✔ No multiple inheritance of state (like in Scala's traits)
  • 20. Default methods resolution rules 1.Classes always win: a method declaration in the class or a superclass takes priority over any default method declaration. 2.Then sub-interfaces win: the method with the same signature in the most specific default-providing interface is selected. 3.If the choice is still ambiguous, the class inheriting from multiple interfaces has to explicitly select which default method implementation to use by overriding it and calling the desired method explicitly. public interface A { default void hello() { System.out.println("Hello from A"); } } public interface B { default void hello() { System.out.println("Hello from B"); } } public class C implements B, A { void hello() { B.super.hello(); } }
  • 21. Example 3 Stream laziness
  • 22. Intermediate & Terminal Operations Return the final result of the operation pipeline Intermediate distinct map, flatMap limit, skip peek sorted Terminal collect count forEach min, max reduce toArray findAny, findFirst allMatch, anyMatch, noneMatch Return another Stream and then can be chained to form a pipeline of operations
  • 23. map : an intermediate operation map( -> ) Stream
  • 24. reduce : a terminal operation Stream Integer reduce(0, (a, b) -> a + b)
  • 25. Putting them all together List<String> strings = asList("Lambda", "expressions", "are", "easy", "and", "useful"); int totalLength = strings.stream() .map(String::length) .reduce(0, (a, b) -> a + b);
  • 26. Stream Operations Pipelining Intermediate Operations are lazy and return another Stream allowing to fluently pipeline other operations Terminal Operations are eager and computes the result of the whole pipeline
  • 27. Example 4 Prime numbers
  • 28. Separation of Concerns List<String> errors = new ArrayList<>(); int errorCount = 0; File file = new File(fileName); String line = file.readLine(); while (errorCount < 40 && line != null) { if (line.startsWith("ERROR")) { errors.add(line); errorCount++; } line = file.readLine(); List<String> errors = Files.lines(Paths.get(fileName)) .filter(l -> l.startsWith("ERROR") .limit(40) .collect(toList()); }
  • 29. Example 5 Stream from a File
  • 30. Grouping Map<Dish.Type, List<Dish>> dishesByType = new HashMap<>(); for (Dish dish : menu) { Dish.Type type = dish.getType(); List<Dish> dishes = dishesByType.get(type); if (dishes == null) { dishes = new ArrayList<>(); dishesByType.put(type, dishes); } dishes.add(dish); }
  • 31. Grouping with Collectors apply key classify item into list next item grouping Map fish meat other salmon pizza rice french fries pork beef chicken prawns Classification Function fish Stream Map<Dish.Type, List<Dish>> dishesByType = menu.stream() .collect(groupingBy(Dish::getType));
  • 33. groupingBy Stream Dish::getType classification function Complex Grouping subStream subStream subStream collectingAndThen reducing result Optional[pork] Optional::get result grouping Map collectingAndThen fish meat other salmon pork pizza reducing collectingAndThen reducing result result The original Stream is divided in subStreams according to the classification function Each subStreams is independently processed by the second Collector transformation function The reducing Collector returns the most caloric Dish wrapped in an Optional The collectingAndThen Collector returns the value extracted from the former Optional The results of the 2nd level Collectors become the values of the grouping map
  • 34. Streams – Parallelism for free parallelStream() employees.stream() .filter(e -> e.getRole() == Role.MANAGER) .map(Employee::getIncome) .reduce(0, (a, b) -> a + b);
  • 37. Is there such thing as a free lunch?
  • 38. Probably yes … … but we need functional forks and knives to eat it
  • 39. Concurrency & Parallelism Parallel programming Running multiple tasks at the same time Concurrent programming Managing concurrent requests Both are hard!
  • 40. The cause of the problem … Mutable state + Parallel processing = Non-determinism Functional Programming
  • 41. Race conditions Deadlocks Starvation Livelocks … and its effects Too hard to think about them!
  • 42. The native Java concurrency model Based on: Locks Synchronization They are sometimes plain evil … Threads Semaphores … and sometimes a necessary pain … … but always the wrong default
  • 43. Different concurrency models Isolated mutable state (actors) Purely immutable (pure functions) Shared mutable state (threads + locks)
  • 44. Summing attendants ages (Threads) class Blackboard { int sum = 0; int read() { return sum; } void write(int value) { sum = value; } } class Attendant implements Runnable { int age; Blackboard blackboard; public void run() { synchronized(blackboard) { int oldSum = blackboard.read(); int newSum = oldSum + age; blackboard.write(newSum); } } }
  • 45. Summing attendants ages (Actors) class Blackboard extends UntypedActors { int sum = 0; public void onReceive(Object message) { if (message instanceof Integer) { sum += (Integer)message; } } } class Attendant { int age; Blackboard blackboard; public void sendAge() { blackboard.sendOneWay(age); } }
  • 46. Summing attendants ages (Functional) class Blackboard { final int sum; Blackboard(int sum) { this.sum = sum; } } class Attendant { int age; Attendant next; public Blackboard addMyAge(Blackboard blackboard) { final Blackboard b = new Blackboard(blackboard.sum + age); return next == null ? b : next.myAge(b); } }
  • 47. The state quadrants Mutable Immutable Shared Unshared Actors Threads Functional Programming Determinism Non-determinism
  • 48. What is a functional program? A program created using only pure functions No side effects allowed like: } }avoidable Reassigning a variable Modifying a data structure in place Setting a field on an object Throwing an exception or halting with an error Printing to the console Reading user input Reading from or writing to a file Drawing on the screen deferrable Functional programming is a restriction on how we write programs, but not on what they can do
  • 49. Example 8 Modularity to confine side-effects
  • 50. A pure functional core functional core a thin external layer to handle side-effects Any function with side-effects can be split into a pure function at the core and a pair of functions with side-effect. This transformation can be repeated to push side-effects to the outer layers of the program.
  • 51. What is a (pure) function? A function with input type A and output type B is a computation which relates every value a of type A to exactly one value b of type B such that b is determined solely by the value of a But, if it really is a function, it will do nothing else
  • 52. Referential transparency An expression e is referentially transparent if for all programs p, all occurrences of e in p can be replaced by the result of evaluating e, without affecting the observable behavior of p A function f is pure if the expression f(x) is referentially transparent for all referentially transparent x
  • 53. RT String x = "purple"; String r1 = x.replace('p', 't'); String r2 = x.replace('p', 't'); String r1 = "purple".replace('p', 't'); r1: "turtle" String r2 = "purple".replace('p', 't'); r2: "turtle" Non-RT StringBuilder x = new StringBuilder("Hi"); StringBuilder y = x.append(", mom"); String r1 = y.toString(); String r2 = y.toString(); String r1 = x.append(", mom").toString(); r1: "Hi, mom" String r2 = x.append(", mom").toString(); r1: "Hi, mom, mom" vs.
  • 54. RT wins Under a developer point of view: Easier to reason about since effects of evaluation are purely local Use of the substitution model: it's possible to replace a term with an equivalent one Under a performance point of view: The JVM is free to optimize the code by safely reordering the instructions No need to synchronize access to shared data Possible to cache the result of time consuming functions (memoization), e.g. with Map.computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)
  • 55. Mutability Parameter binding is about assigning names to things Mutating variables is about assigning things to names Does that second one sound weird? … well it's because it IS weird
  • 56. Immutability Immutable objects can be shared among many threads exactly because none of them can modify it In the same way immutable (persistent) data structures can be shared without any need to synchronize the different threads accessing them
  • 57. Old Root New Root 5 8 7 9 3 4 E E E E E E E 5 3 2 E E Persistent Collections Shared data
  • 58. Example 9 Avoiding mutability
  • 59. NullPointerException Raise your hand if you've ever seen this
  • 60. Null references? No, Thanks ✗ Errors source → NPE is by far the most common exception in Java ✗ Bloatware source → Worsen readability by making necessary to fill our code with null checks ✗ Meaningless → Don't have any semantic meaning and in particular are the wrong way to model the absence of a value in a statically typed language ✗ Breaks Java philosophy → Java always hides pointers to developers, except in one case: the null pointer ✗ A hole in the type system → Null has the bottom type, meaning that it can be assigned to any reference type: this is a problem because, when propagated to another part of the system, you have no idea what that null was initially supposed to be Tony Hoare, who invented the null reference in 1965 while working on an object oriented language called ALGOL W, called its invention his “billion dollar mistake”
  • 61. Replacing nulls with Optionals If nulls are so problematic why don't we just avoid them? Optional value value Optional EMPTY null Optional is a type that models a possibly missing value
  • 62. public class Person { private Car car; public Car getCar() { return car; } } public class Car { private Insurance insurance; public Insurance getInsurance() { return insurance; } } public class Insurance { private String name; public String getName() { return name; } } Finding Car's Insurance Name
  • 63. String getCarInsuranceName(Person person) { if (person != null) { Car car = person.getCar(); if (car != null) { Insurance insurance = car.getInsurance(); if (insurance != null) { return insurance.getName() } } } return "Unknown"; } Attempt 1: deep doubts
  • 64. Attempt 2: too many choices String getCarInsuranceName(Person person) { if (person == null) { return "Unknown"; } Car car = person.getCar(); if (car == null) { return "Unknown"; } Insurance insurance = car.getInsurance(); if (insurance == null) { return "Unknown"; } return insurance.getName() }
  • 65. Optional to the rescue public class Optional<T> { private static final Optional<?> EMPTY = new Optional<>(null); private final T value; private Optional(T value) { this.value = value; } public<U> Optional<U> map(Function<? super T, ? extends U> f) { return value == null ? EMPTY : new Optional(f.apply(value)); } public<U> Optional<U> flatMap(Function<? super T, Optional<U>> f) { return value == null ? EMPTY : f.apply(value); } }
  • 66. public class Person { private Optional<Car> car; public Optional<Car> getCar() { return car; } } public class Car { private Optional<Insurance> insurance; public Optional<Insurance> getInsurance() { return insurance; } } public class Insurance { private String name; public String getName() { return name; } } Rethinking our model Using the type system to model nullable value
  • 67. String getCarInsuranceName(Optional<Person> person) { return person.flatMap(person -> person.getCar()) .flatMap(car -> car.getInsurance()) .map(insurance -> insurance.getName()) .orElse("Unknown"); } Restoring the sanity
  • 68. String getCarInsuranceName(Optional<Person> person) { return person.flatMap(person -> person.getCar()) .flatMap(car -> car.getInsurance()) .map(insurance -> insurance.getName()) .orElse("Unknown"); } Restoring the sanity Optional Person
  • 69. String getCarInsuranceName(Optional<Person> person) { return person.flatMap(person -> person.getCar()) .flatMap(car -> car.getInsurance()) .map(insurance -> insurance.getName()) .orElse("Unknown"); } Restoring the sanity Optional Person flatMap(person -> person.getCar())
  • 70. String getCarInsuranceName(Optional<Person> person) { return person.flatMap(person -> person.getCar()) .flatMap(car -> car.getInsurance()) .map(insurance -> insurance.getName()) .orElse("Unknown"); } Restoring the sanity Optional flatMap(person -> person.getCar()) Optional Car
  • 71. String getCarInsuranceName(Optional<Person> person) { return person.flatMap(person -> person.getCar()) .flatMap(car -> car.getInsurance()) .map(insurance -> insurance.getName()) .orElse("Unknown"); } Restoring the sanity Optional flatMap(car -> car.getInsurance()) Car
  • 72. String getCarInsuranceName(Optional<Person> person) { return person.flatMap(person -> person.getCar()) .flatMap(car -> car.getInsurance()) .map(insurance -> insurance.getName()) .orElse("Unknown"); } Restoring the sanity Optional flatMap(car -> car.getInsurance()) Optional Insurance
  • 73. String getCarInsuranceName(Optional<Person> person) { return person.flatMap(person -> person.getCar()) .flatMap(car -> car.getInsurance()) .map(insurance -> insurance.getName()) .orElse("Unknown"); } Restoring the sanity Optional map(insurance -> insurance.getName()) Insurance
  • 74. String getCarInsuranceName(Optional<Person> person) { return person.flatMap(person -> person.getCar()) .flatMap(car -> car.getInsurance()) .map(insurance -> insurance.getName()) .orElse("Unknown"); } Restoring the sanity Optional orElse("Unknown") String
  • 75. Example 10 Using Optional
  • 76. Thinking in Functions Learning a new language is relatively easy compared with learning a new paradigm. Functional Programming is more a new way of thinking than a new tool set
  • 77. Example 11 The Loan Pattern
  • 78. Example 12 Conditional deferred execution
  • 79. Futures, weren't they enough? The Future interface was introduced in Java 5 to model an asynchronous computation and then provide an handle to a result that will be made available at some point in the future. But it doesn't allow to: ✗ Combining two asynchronous computations in one ✗ Waiting for the completion of all tasks performed by a set of Futures ✗ Waiting for the completion of only the quickest task in a set of Futures (possibly because they’re trying to calculate the same value in different ways) and retrieving its result ✗ Programmatically completing a Future ✗ Reacting to a Future completion
  • 80. CompletableFutures to the rescue ✔ Programmatically completing a Future with a result … boolean complete(T value) … or an error boolean completeExceptionally(Throwable ex) ✔ Reacting to Future completion CompletableFuture<Void> thenAccept(Consumer<? super T> action) ✔ Combining 2 async operation in sequence ... static CompletableFuture<U> thenCompose( Function<? super T,? extends CompletionStage<U>> fn) … or in parallel static CompletableFuture<V> thenCombine( CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn) ✔ Waiting for the completion of all Futures ... static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs) … or only the fastest one static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)
  • 81. Example 13 Putting CompletableFutures at work
  • 82. Key Takeaways Think in functions Strive for immutability Confine side-effects Avoid blocking code Cede control with higher-order functions Leverage referential transparency Use FP to design more composable and reusable API Model potentially missing values with Optionals … but there are no dogmas Be pragmatic and use the right tool for the job at hand Poly-paradigm programming is more powerful and effective than polyglot programming
  • 83. The bottom line Java is getting functional EMBRACE IT!
  • 84.
  • 85. Thanks … Questions? Q A Mario Fusco Red Hat – Senior Software Engineer mario.fusco@gmail.com twitter: @mariofusco code examples @ https://github.com/mariofusco/Java8WS