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

Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented ProgrammingScott Wlaschin
 
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 WrongMario 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
 
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,...Chris Richardson
 
The Functional Programming Toolkit (NDC Oslo 2019)
The Functional Programming Toolkit (NDC Oslo 2019)The Functional Programming Toolkit (NDC Oslo 2019)
The Functional Programming Toolkit (NDC Oslo 2019)Scott Wlaschin
 
Spring Data JPA from 0-100 in 60 minutes
Spring Data JPA from 0-100 in 60 minutesSpring Data JPA from 0-100 in 60 minutes
Spring Data JPA from 0-100 in 60 minutesVMware Tanzu
 
Java 8 presentation
Java 8 presentationJava 8 presentation
Java 8 presentationVan Huong
 
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.David Gómez García
 
Being Functional on Reactive Streams with Spring Reactor
Being Functional on Reactive Streams with Spring ReactorBeing Functional on Reactive Streams with Spring Reactor
Being Functional on Reactive Streams with Spring ReactorMax Huang
 
Polymorphism In Java
Polymorphism In JavaPolymorphism In Java
Polymorphism In JavaSpotle.ai
 
Domain Driven Design with the F# type System -- F#unctional Londoners 2014
Domain Driven Design with the F# type System -- F#unctional Londoners 2014Domain Driven Design with the F# type System -- F#unctional Londoners 2014
Domain Driven Design with the F# type System -- F#unctional Londoners 2014Scott Wlaschin
 
How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021
How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021
How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021Natan Silnitsky
 
The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)Scott Wlaschin
 

What's hot (20)

Lazy java
Lazy javaLazy java
Lazy java
 
Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented Programming
 
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...
 
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,...
 
The Functional Programming Toolkit (NDC Oslo 2019)
The Functional Programming Toolkit (NDC Oslo 2019)The Functional Programming Toolkit (NDC Oslo 2019)
The Functional Programming Toolkit (NDC Oslo 2019)
 
Clean code
Clean codeClean code
Clean code
 
Completable future
Completable futureCompletable future
Completable future
 
Clean code
Clean codeClean code
Clean code
 
Java 8 Lambda and Streams
Java 8 Lambda and StreamsJava 8 Lambda and Streams
Java 8 Lambda and Streams
 
Spring Data JPA from 0-100 in 60 minutes
Spring Data JPA from 0-100 in 60 minutesSpring Data JPA from 0-100 in 60 minutes
Spring Data JPA from 0-100 in 60 minutes
 
Java 8 presentation
Java 8 presentationJava 8 presentation
Java 8 presentation
 
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.
 
Being Functional on Reactive Streams with Spring Reactor
Being Functional on Reactive Streams with Spring ReactorBeing Functional on Reactive Streams with Spring Reactor
Being Functional on Reactive Streams with Spring Reactor
 
Polymorphism In Java
Polymorphism In JavaPolymorphism In Java
Polymorphism In Java
 
Domain Driven Design with the F# type System -- F#unctional Londoners 2014
Domain Driven Design with the F# type System -- F#unctional Londoners 2014Domain Driven Design with the F# type System -- F#unctional Londoners 2014
Domain Driven Design with the F# type System -- F#unctional Londoners 2014
 
Java 8 lambda
Java 8 lambdaJava 8 lambda
Java 8 lambda
 
Java NIO.2
Java NIO.2Java NIO.2
Java NIO.2
 
How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021
How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021
How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021
 
The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)
 

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 beyondMario Fusco
 
No more loops with lambdaj
No more loops with lambdajNo more loops with lambdaj
No more loops with lambdajMario Fusco
 
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 ProgrammerMario Fusco
 
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...Mario Fusco
 
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 JVMMario Fusco
 
Scala - where objects and functions meet
Scala - where objects and functions meetScala - where objects and functions meet
Scala - where objects and functions meetMario Fusco
 
Why we cannot ignore Functional Programming
Why we cannot ignore Functional ProgrammingWhy we cannot ignore Functional Programming
Why we cannot ignore Functional ProgrammingMario 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 languageMario Fusco
 
Drools 6 deep dive
Drools 6 deep diveDrools 6 deep dive
Drools 6 deep diveMario Fusco
 
Functional programming with Java 8
Functional programming with Java 8Functional programming with Java 8
Functional programming with Java 8LivePerson
 
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 8Simon Ritter
 
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 2014Fredrik Vraalsen
 
Java 8 - Nuevas características
Java 8 - Nuevas característicasJava 8 - Nuevas características
Java 8 - Nuevas característicasFernando Petrola
 
Taxonomy of Scala
Taxonomy of ScalaTaxonomy of Scala
Taxonomy of Scalashinolajla
 
Hanoi jug java 8 stream api
Hanoi jug   java 8 stream apiHanoi jug   java 8 stream api
Hanoi jug java 8 stream apiVu Dang Ngoc
 
NixCon Berlin 2015 - Nix at LogicBlox
NixCon Berlin 2015 - Nix at LogicBloxNixCon Berlin 2015 - Nix at LogicBlox
NixCon Berlin 2015 - Nix at LogicBloxRob Vermaas
 
Deploying (micro)services with Disnix
Deploying (micro)services with DisnixDeploying (micro)services with Disnix
Deploying (micro)services with DisnixSander van der Burg
 

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...
 
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
 
DC4 / C14
DC4 / C14DC4 / C14
DC4 / C14
 
Deploying (micro)services with Disnix
Deploying (micro)services with DisnixDeploying (micro)services with Disnix
Deploying (micro)services with Disnix
 

Similar to Java 8 Workshop

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 programmingHenri Tremblay
 
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...Akaks
 
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 Ganesh Samarthyam
 
SOLID mit Java 8
SOLID mit Java 8SOLID mit Java 8
SOLID mit Java 8Roland Mast
 
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 useSharon Rozinsky
 
java150929145120-lva1-app6892 (2).pptx
java150929145120-lva1-app6892 (2).pptxjava150929145120-lva1-app6892 (2).pptx
java150929145120-lva1-app6892 (2).pptxBruceLee275640
 
Java 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional InterfacesJava 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional InterfacesGanesh Samarthyam
 
The... Wonderful? World of Lambdas
The... Wonderful? World of LambdasThe... Wonderful? World of Lambdas
The... Wonderful? World of LambdasEsther Lozano
 
Thumbtack Expertise Days # 5 - Javaz
Thumbtack Expertise Days # 5 - JavazThumbtack Expertise Days # 5 - Javaz
Thumbtack Expertise Days # 5 - JavazAlexey Remnev
 

Similar to Java 8 Workshop (20)

Java gets a closure
Java gets a closureJava gets a closure
Java gets a closure
 
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 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional InterfacesJava 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional Interfaces
 
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

Kogito: cloud native business automation
Kogito: cloud native business automationKogito: cloud native business automation
Kogito: cloud native business automationMario Fusco
 
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...Mario Fusco
 
Introducing Drools
Introducing DroolsIntroducing Drools
Introducing DroolsMario 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 forwardMario Fusco
 
Swiss army knife Spring
Swiss army knife SpringSwiss army knife Spring
Swiss army knife SpringMario 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 & STMMario Fusco
 

More from Mario Fusco (7)

Kogito: cloud native business automation
Kogito: cloud native business automationKogito: cloud native business automation
Kogito: cloud native business automation
 
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

Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️anilsa9823
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfkalichargn70th171
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...soniya singh
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsAndolasoft Inc
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationkaushalgiri8080
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfjoe51371421
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AIABDERRAOUF MEHENNI
 

Recently uploaded (20)

Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanation
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
 
Exploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the ProcessExploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the Process
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
 

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