SlideShare une entreprise Scribd logo
1  sur  53
Télécharger pour lire hors ligne
JAVA 8 - BY EXAMPLE!
PATTERNS AND PRACTICES FOR LAMBDAS, STREAMS,
OPTIONAL...
Createdby /MarkHarrison @markglh
INTERFACE DEFAULT METHODS
Interfaces can now have default & static methods!
Allows new interface methods to be added without breaking
existing implementations
Multiple inheritance!
public interface Comparator<T> {
default Comparator<T> reversed() {
// Implementation here
}
public static Comparator<T> naturalOrder() {
// Implementation here
}
}
MULTIPLE INHERITANCE...
What if a class inherits the same default method from two
interfaces???
1.Class methods always win. Whether it’s this class or the
superclass, it will take priority
2.If multiple interfaces de ne the same method with a
default implementation, then the most speci c is selected
(the child in inheritance terms)
3.If it’s not obvious then the compiler will cry, we need to
explicitly choose: INTERFACE.super.METHODNAME
LAMBDAS YOU SAY?
Basically just a shorthand method implementation
Concise and much improved replacement for Anonymous
inner classes
Makes it easy to pass behaviour around
Pass the behaviour into the method, ips the design on its
head
Lexically scoped (this is effectively shared with the
surrounding method)
SYNTAX PLEASE!
(int x, int y) -> x + y
Argument types can be inferred by the compiler:
(x, y) -> x + y
Zero-arg Lambdas are also possible:
() -> "Java 8!"
But how can we use them?
Consumer<String> inferredConsumer =
x -> System.out.println(x);
WAT?!?
FUNCTIONAL INTERFACES
A Functional Interface is any interface with one Single
Abstract Method
The parameters that the Lambda accepts and returns must
match the interface (including exceptions)
@FunctionalInterface annotation is provided to
highlight these interfaces, it is just a marker though, any SAM
interface will work - the annotation simply enforces this at
compile time
So... When we pass or assign a Lambda:
1. First the Lambda is converted into a Functional Interface
2. Secondly it is invoked via this generated implementation
LAMBDA EXAMPLE 1 - PREDICATES
Have you ever written code like this?
@FunctionalInterface //Added in Java8
public interface Predicate<T> {
boolean test(T t);
}
private void printMatchingPeople(
List<Person> people,
Predicate<Person> predicate) {
for (Person person : people) {
if (predicate.test(person)) {
System.out.println(person);
}
}
}
LAMBDA EXAMPLE 1 - PREDICATES
Pre Java 8:
public class PersonOver50Predicate
implements Predicate<Person> {
public boolean test(Person person) {
return person.getAge() > 50;
}
}
printMatchingPeople(loadsOfPeople,
new PersonOver50Predicate());
LAMBDA EXAMPLE 1 - PREDICATES
Java 8:
printMatchingPeople(loadsOfPeople,
x -> x.getAge() > 50);
Notice the signature matches that of the Predicate, the compiler
automatically gures out the rest
What if we had an existing Predicate we wanted to enhance?
Composite Predicates FTW... :-)
Predicate<Person> ageCheck = x -> x.getAge() > 50;
printMatchingPeople(loadsOfPeople,
ageCheck.and(x -> x.getIq() > 100));
LAMBDA EXAMPLE 2 - RUNNABLE
Pre Java 8 mess:
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("Meh!");
}
};
r1.run();
Java 8:
Runnable r = () -> System.out.println("Woop!");
r.run();
LAMBDA EXAMPLE 3 - COLLECTIONS
Lambdas make lots of new Collection methods possible...
List<String> strings = new ArrayList<>();
Collections.addAll(strings, "Java", "7", "FTW");
Do something on every element in the List
strings.forEach(x -> System.out.print(x + " "));
//Prints: "Java 7 FTW"
LAMBDA EXAMPLE 4 - MORE COLLECTIONS
Replace every matching element in the List
strings.replaceAll(x -> x == "7" ? "8" : x);
strings.forEach(x -> System.out.print(x + " "));
//Prints: "Java 8 FTW"
Remove matching elements from the List
strings.removeIf(x -> x == "8");
strings.forEach(x -> System.out.print(x + " "));
//Prints: Java FTW
LAMBDA EXAMPLE 5 - COMPARATORS
@FunctionalInterface //Added in Java8 version
public interface Comparator<T> {
int compare(T o1, T o2);
//Java 8 adds loads of default methods
}
LAMBDA EXAMPLE 6 - COMPARATORS 2
List<Person> loadsOfPeople = ...;
Pre Java 8:
public class SortByPersonAge
implements Comparator<Person> {
public int compare(Person p1, Person p2) {
return p1.getAge() - p2.getAge();
}
}
Collections.sort(loadsOfPeople,
new SortByPersonAge());
Java 8:
Collections.sort(loadsOfPeople,
(p1, p2) -> p1.getAge() - p2.getAge());
LAMBDA EXAMPLE 7 - COMPARATORS 3
As usual in Java 8... the Comparator interface provides plenty
of useful default & static methods...
//"comparing" static method simplifies creation
Comparator<Person> newComparator =
Comparator.comparing(e -> e.getIq());
//"thenComparing" combines comparators
Collections.sort(loadsOfPeople,
newComparator.thenComparing(
Comparator.comparing(e -> e.getAge())));
LAMBDA EXAMPLE 8 - COMPARATORS 4
and more...
//More useful Collection methods...
loadsOfPeople4.sort(
Comparator.comparing(e -> e.getIq()));
//And finally... Method references
loadsOfPeople.sort(
Comparator.comparing(Person::getAge));
INTRODUCING METHOD REFERENCES
Any method can be automatically “lifted” into a function. It
must simply meet contract of the FunctionalInterface
Can be easier to debug & test than Lambdas, more descriptive
stack traces
Promotes re-use, keeping code DRY
Uses the "::" syntax
METHOD REFERENCES TYPES
Reference to... Example
a static method Class::staticMethodName
an instance method of
a speci c object
object::instanceMethodName
an instance method of
an arbitrary object
Class::methodName
a constructor ClassName::new
REFERENCE TO A STATIC METHOD
A simple reference to a static method
//isPersonOver50 is a static method
printMatchingPeople(loadsOfPeople,
PersonPredicates::isPersonOver50);
This is equivalent to
printMatchingPeople(loadsOfPeople,
x -> x.getAge() > 50);
REFERENCE TO AN INSTANCE METHOD OF A
SPECIFIC OBJECT
A reference to a method on an object instance
List<String> strings = ...
//print is a method on the "out" PrintStream object
strings.forEach(System.out::print);
This is equivalent to
strings.forEach(x -> System.out.print(x));
REFERENCE TO AN INSTANCE METHOD OF AN
ARBITRARY OBJECT
Examine this simpli ed de nition of a map function
public interface Function<T,R> {
public R apply(T t);
}
public <T, R> List<R> map(Function<T, R> function,
List<T> source) {
/* applies the function to each element,
converting it from T to R */
}
REFERENCE TO AN INSTANCE METHOD OF AN
ARBITRARY OBJECT CONT...
Although it looks like we're referencing a Class method, we're
invoking an instance method on the object(s) passed in the call
List<Person> loadsOfPeople = ...
List<Integer> namesOfPeople =
map(Person::getAge, loadsOfPeople);
This is equivalent to
map(person -> person.getAge(), loadsOfPeople);
REFERENCE TO A CONSTRUCTOR
Uses the constructor to create new objects, the constructor
signature must match that of the @FunctionalInterface
List<String> digits = Arrays.asList("1", "2", "3");
//Transforms a String into a new Integer
List<Integer> numbers = map(Integer::new, digits);
This is equivalent to
map(s -> new Integer(s), digits);
WHAT'S WRONG WITH COLLECTIONS
Every application uses Collections, however Collections are
dif cult to query and aggregate, requiring several levels of
iteration and conditionals, basically it’s messy and painful
Writing multi-threaded code to do this manually is dif cult to
write and maintain
Imagine writing this manually
Stream<String> words=Stream.of("Java", "8", "FTW");
Map<String, Long> letterToNumberOfOccurrences =
words.map(w -> w.split(""))
.flatMap(Arrays::stream)
.collect(Collectors.groupingBy(
Function.identity(),
Collectors.counting()));
//Prints: //{a=2, T=1, F=1, v=1, W=1, 8=1, J=1}
INTRODUCING STREAMS!
A Stream is a conceptually xed data structure in which
elements are computed on demand
Streams iterate internally, you don’t have to worry about
handling the iteration
Pipelining: Akin to the “pipe” command in unix, allowing
aggregations to be chained together
Automatic optimisation: short-circuiting and lazy processing
Can be in nite
Can be executed in parallel automatically using
parallelStream or parallel()
MORE STREAMS...
Can be created from multiple sources:
Arrays.stream(...), Stream.of(1, 2, 3, 4),
Stream.iterate(...), Stream.range(...),
Random.ints(), Files.lines(...)...
Two types of operations:
Intermediate (aggregation): lter, map, atMap, sorted ...
Terminal: collect, reduce, forEach, ndAny ...
Specialised Streams:
IntStream, LongStream and DoubleStream: better
performance for those unboxed types
MAP
public <R> Stream<R> map(Function<T, R> mapper);
The mapper Function converts each element from T to R. The
result is then added, as is, to the Stream
FLATMAP
public <R> Stream<R> flatMap(Function<T,
Stream<R>> mapper);
The mapper Function converts each element from T to a
Stream of R
This is the key difference to map, the function itself returns a
Stream rather than one element
This Stream is then attened (merged) into the main Stream
To put it another way: atMap lets you replace each value of a
Stream with another Stream, and then it concatenates all the
generated streams into one single stream
REDUCE
public T reduce(T identity,
BinaryOperator<T> accumulator);
public Optional<T> reduce(
BinaryOperator<T> accumulator);
//This is the function contained in BinaryOperator
R apply(T t, U u);
Terminal Operation
Takes a Stream of values and repeatedly applies the
accumulator to reduce them into a single value
The accumulator is passed the total so far (T) and the current
element (U)
If passed, identity provides the initial value, rather than the
rst element
REDUCE CONTINUED...
int totalAgeUsingReduce = loadsOfPeople.stream()
.map(Person::getAge) //contains 5, 10, 15
.reduce(0, (total, current) -> total + current);
1.First we map the Person to the age int
2.reduce then starts at 0, and adds the current element, 5
3.reduce continues by adding the current total 5, to the next
element, 10
4. nally reduce adds the current total 15, to the next element
15
5.Tada, we've added up all the ages: 30!
COLLECTORS
The collect method is a terminal operation which takes various
"recipes", called Collectors for accumulating the elements of
a stream into a summary result, or converting to a speci c type
(such as a List)
List<String> listOfStrings = loadsOfPeople.stream()
.map(x -> x.getName())
.collect(Collectors.toList());
The argument passed to collect is an object of type java
.util.stream.Collector
It describes how to accumulate the elements of a stream into
a nal result
Can be used for Grouping, Partitioning, Averaging, ...
STREAMS EXAMPLE 1
List<Integer> numbers = Arrays.asList(1, 2 ... 8);
List<Integer> twoEvenSquares = numbers.stream()
.filter(n -> n % 2 == 0) //Filter odd numbers
.map(n -> n * n) ////Multiply by itself
.limit(2)//Limit to two results
.collect(Collectors.toList()); //Finish!
Imagine a println in each step...
filtering 1
filtering 2
mapping 2
filtering 3
filtering 4
mapping 4
twoEvenSquares = List[4, 16]
STREAMS EXAMPLE 2
List<String> youngerPeopleSortedByIq =
loadsOfPeople.stream()
.filter(x -> x.getAge() < 50)
.sorted(Comparator
.comparing(Person::getIq).reversed())
.map(Person::getName)
.collect(Collectors.toList());
1. Filter out all people older than 50
2. Inverse sort the remaining people by IQ
3. map each person to their name (convert to a Stream<String>)
4. Convert the result to a List
STREAMS EXAMPLE 3 - SUM
int combinedAge =
loadsOfPeople.stream()
.mapToInt(Person::getAge) //returns IntStream
.sum(); //this HAS to be a specialised Stream
1. map each person to their age, producing an IntStream
2. sum the results, also supports average
STREAMS EXAMPLE 4 - MAP, REDUCE
String xml =
"<people>" +
loadsOfPeople.stream()
.map(x -> "<person>"+ x.getName() +"</person>")
.reduce("", String::concat) //start with ""
+ "</people>";
map each Person to an XML element
(<person>Steve</person>), then use String.concat to reduce
the Stream into one XML String
<people>
<person>Dave</person>
<person>Helen</person>
<person>Laura</person>
<person>Ben</person>
</people>
STREAMS EXAMPLE 5 - MAP
List<Stream<Person>> clonedPeople =
loadsOfPeople.stream()
.map(person -> Stream.of(person, person.dolly()))
.collect(Collectors.toList());
1.map creates a new Stream containing two people
2.This Stream is then added to the main Stream as-is, leaving
us with a pretty useless: List<Stream<Person>>
STREAMS EXAMPLE 6 - FLATMAP
List<Person> clonedPeople2 = loadsOfPeople.stream()
.flatMap(person -> Stream.of(person,
person.dolly()))
.collect(Collectors.toList());
1. atMap combines each element from the new Streams into
one Stream<Person>
2.So now we've got what we wanted in the rst place, a
List<Person>
Sweeet!
STREAMS EXAMPLE 7 - REDUCE
int totalAgeUsingReduce = loadsOfPeople.stream()
.map(Person::getAge)
.reduce((total, current) -> total + current)
.get(); //get the result from the Optional
This is the same as the previous example, the difference being
we don't specify a default value for reduce
Not specifying a default value means the result is Optional...
if the Stream is empty then so is the result!
STREAMS EXAMPLE 8 - GROUPING
Map<Integer, List<Person>> peopleGroupedByAge =
loadsOfPeople.stream()
.filter(x -> x.getIq() > 110)
.collect(Collectors.groupingBy(Person::getAge));
The collect method groups the ltered results by age,
producing a Map<age, <Person>>
{52=[Person{... age=52, iq=113, gender=MALE}],
60=[Person{... age=60, iq=120, gender=FEMALE}],
28=[Person{... age=28, iq=190, gender=MALE}]}
STREAMS EXAMPLE 9 - PARTITIONING
Map<Boolean, List<Person>> peoplePartitionedByAge =
loadsOfPeople.stream().filter(x -> x.getIq() > 110)
.collect(Collectors
.partitioningBy(x -> x.getAge() > 55));
The collect method partitions the ltered results by age
The Map will have two entries, true and false, according to the
Predicate
{false=[Person{... age=28, iq=190, gender=MALE}],
true=[Person{... age=60, iq=120, gender=FEMALE}]}
STREAMS EXAMPLE 10 - MULTIPLE GROUPS
Map<Integer, Double> peopleGroupedBySexAndAvgAge =
loadsOfPeople.stream()
.filter(x -> x.getIq() > 110)
.collect(
Collectors.groupingBy(Person::getAge,
Collectors.averagingInt(Person::getIq)));
We can group by multiple Collectors
Here we group by age and the average IQ of that group
{52=113.0, 60=117.5, 28=190.0}
STREAMS EXAMPLE 11 - FINDANY
loadsOfPeople.stream()
.filter(t -> t.getGender() == Person.Sex.FEMALE)
.findAny()
.ifPresent(System.out::println);
findAny either returns an element or nothing, hence we get
an Optional
ifPresent executes the Lambda if we get a result
STREAMS EXAMPLE 12 - PARALLEL
Lets iterate over 10,000,000 elements!
x -> Stream.iterate(1L, i -> i + 1)
.limit(x)
.reduce(Long::sum).get();
Executes in 80ms - we incur a penalty here because the long is
repeatedly boxed and unboxed
Executes in 211ms?! It turns out parallel isn't always a free win!
x -> Stream.iterate(1L, i -> i + 1)
.parallel().limit(x)
.reduce(Long::sum).get();
STREAMS EXAMPLE 13 - PARALLEL WIN!
x -> LongStream.rangeClosed(1L, x)
.reduce(Long::sum).getAsLong();
Executes in 24ms - much better using an unboxed Stream
Executes in 7ms - now that the Stream isn't dynamic, parallel
works much better!
x -> LongStream.rangeClosed(1L, x)
.parallel()
.reduce(Long::sum).getAsLong();
OPTIONAL
Use Optional instead of passing null around, helps prevent
NullPointerExceptions
Optional is a container that’s either empty or present, in
which case it contains a value
So anytime that you’re thinking of return or accepting a null
value in a method, use Optional instead!
public class Computer {
private Optional<Mainboard> mainboard;
}
public class Mainboard {
private Optional<Cpu> cpu;
}
public class Cpu {
private String type;
}
USING OPTIONAL
Several ways to create an Optional:
Optional.of(cpu); //Throws an NPE if cpu is null
Optional.ofNullable(cpu); //empty if cpu is null
Getting the contents from the Optional:
cpu.get(); //get CPU or throw NoSuchElementException
cpu.orElse(new Cpu()); //safe get, provides default
And more...
cpu.isPresent(); //true if present, false if empty
cpu.ifPresent(x -> System.out.println(x.getType()));
Also supports map, atMap and lter!
OPTIONAL EXAMPLE 1 - BASICS
if (mainboard.isPresent() &&
mainboard.get().getCpu().isPresent()) {
mainboard.get().getCpu().get().getType();
}
Eww! Lets try something else!
***Fails to compile, calling getType on an Optional... if only
we could atten it???
Optional<String> cpuType =
mainboard.map(Mainboard::getCpu)
.map(Cpu::getType); //Optional<Optional<Cpu>>
OPTIONAL EXAMPLE 2 - FLATMAP
Optional<String> stringOptional = mainboard
.flatMap(Mainboard::getCpu)
.map(Cpu::getType);
Lets take this further and safely get cpu type of a Computer!
Computer computer = new Computer(mainboard);
String cpu = computer.getMainboard()
.flatMap(Mainboard::getCpu)
.map(Cpu::getType)
.filter(x -> "Intel".equals(x))
.orElse("Nothing we're interested in!");
IT'S BEEN EMOTIONAL...
Slides at
Source at
Follow me
markglh.github.io/Java8Madlab-Slides
github.com/markglh/Java8Madlab-Examples
@markglh
RECOMMENDED READING
Lambdas Part 1 (Ted Neward)
Lambdas Part 2 (Ted Neward)
Lambda Expressions vs Method References (Edwin Dalorzo)
Youtube: Java 8 - more readable and exible code (Raoul-
Gabriel Urma)
Youtube: Lambda Expressions & Streams (Adib Saikali)
Java 8 Streams Part 1 (Raoul-Gabriel Urma)
Java 8 Streams Part 2 (Raoul-Gabriel Urma)
Optional - No more NPE's (Raoul-Gabriel Urma)

Contenu connexe

Tendances

Introduction to Java 8
Introduction to Java 8Introduction to Java 8
Introduction to Java 8Knoldus Inc.
 
Functional Java 8 - Introduction
Functional Java 8 - IntroductionFunctional Java 8 - Introduction
Functional Java 8 - IntroductionŁukasz Biały
 
Functional programming in java 8 by harmeet singh
Functional programming in java 8 by harmeet singhFunctional programming in java 8 by harmeet singh
Functional programming in java 8 by harmeet singhHarmeet Singh(Taara)
 
Java 8 Streams And Common Operations By Harmeet Singh(Taara)
Java 8 Streams And Common Operations By Harmeet Singh(Taara)Java 8 Streams And Common Operations By Harmeet Singh(Taara)
Java 8 Streams And Common Operations By Harmeet Singh(Taara)Harmeet Singh(Taara)
 
java 8 new features
java 8 new features java 8 new features
java 8 new features Rohit Verma
 
10 Sets of Best Practices for Java 8
10 Sets of Best Practices for Java 810 Sets of Best Practices for Java 8
10 Sets of Best Practices for Java 8Garth Gilmour
 
Lambda Expressions in Java
Lambda Expressions in JavaLambda Expressions in Java
Lambda Expressions in JavaErhan Bagdemir
 
Functional programming principles and Java 8
Functional programming principles and Java 8Functional programming principles and Java 8
Functional programming principles and Java 8Dragos Balan
 
Lambda Expressions in Java 8
Lambda Expressions in Java 8Lambda Expressions in Java 8
Lambda Expressions in Java 8icarter09
 
Functional Java 8 in everyday life
Functional Java 8 in everyday lifeFunctional Java 8 in everyday life
Functional Java 8 in everyday lifeAndrea Iacono
 
Programming with Lambda Expressions in Java
Programming with Lambda Expressions in Java Programming with Lambda Expressions in Java
Programming with Lambda Expressions in Java langer4711
 

Tendances (20)

Introduction to Java 8
Introduction to Java 8Introduction to Java 8
Introduction to Java 8
 
Functional Java 8 - Introduction
Functional Java 8 - IntroductionFunctional Java 8 - Introduction
Functional Java 8 - Introduction
 
Java 8 features
Java 8 featuresJava 8 features
Java 8 features
 
Functional programming in java 8 by harmeet singh
Functional programming in java 8 by harmeet singhFunctional programming in java 8 by harmeet singh
Functional programming in java 8 by harmeet singh
 
Java 8 Streams And Common Operations By Harmeet Singh(Taara)
Java 8 Streams And Common Operations By Harmeet Singh(Taara)Java 8 Streams And Common Operations By Harmeet Singh(Taara)
Java 8 Streams And Common Operations By Harmeet Singh(Taara)
 
Java8
Java8Java8
Java8
 
java 8 new features
java 8 new features java 8 new features
java 8 new features
 
Java 8 Feature Preview
Java 8 Feature PreviewJava 8 Feature Preview
Java 8 Feature Preview
 
10 Sets of Best Practices for Java 8
10 Sets of Best Practices for Java 810 Sets of Best Practices for Java 8
10 Sets of Best Practices for Java 8
 
Java 8 ​and ​Best Practices
Java 8 ​and ​Best PracticesJava 8 ​and ​Best Practices
Java 8 ​and ​Best Practices
 
Lambda Expressions in Java
Lambda Expressions in JavaLambda Expressions in Java
Lambda Expressions in Java
 
Java SE 8 library design
Java SE 8 library designJava SE 8 library design
Java SE 8 library design
 
Java 8 new features
Java 8 new featuresJava 8 new features
Java 8 new features
 
Functional programming principles and Java 8
Functional programming principles and Java 8Functional programming principles and Java 8
Functional programming principles and Java 8
 
Java 8 lambda
Java 8 lambdaJava 8 lambda
Java 8 lambda
 
Lambda Expressions in Java 8
Lambda Expressions in Java 8Lambda Expressions in Java 8
Lambda Expressions in Java 8
 
Actors model in gpars
Actors model in gparsActors model in gpars
Actors model in gpars
 
Functional Java 8 in everyday life
Functional Java 8 in everyday lifeFunctional Java 8 in everyday life
Functional Java 8 in everyday life
 
Java 8 Features
Java 8 FeaturesJava 8 Features
Java 8 Features
 
Programming with Lambda Expressions in Java
Programming with Lambda Expressions in Java Programming with Lambda Expressions in Java
Programming with Lambda Expressions in Java
 

Similaire à Java 8 by example!

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
 
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
 
Java 8 - An Overview
Java 8 - An OverviewJava 8 - An Overview
Java 8 - An OverviewIndrajit Das
 
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
 
FUNctional Programming in Java 8
FUNctional Programming in Java 8FUNctional Programming in Java 8
FUNctional Programming in Java 8Richard Walker
 
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
 
java150929145120-lva1-app6892 (2).pptx
java150929145120-lva1-app6892 (2).pptxjava150929145120-lva1-app6892 (2).pptx
java150929145120-lva1-app6892 (2).pptxBruceLee275640
 
A Brief Conceptual Introduction to Functional Java 8 and its API
A Brief Conceptual Introduction to Functional Java 8 and its APIA Brief Conceptual Introduction to Functional Java 8 and its API
A Brief Conceptual Introduction to Functional Java 8 and its APIJörn Guy Süß JGS
 
Xebicon2013 scala vsjava_final
Xebicon2013 scala vsjava_finalXebicon2013 scala vsjava_final
Xebicon2013 scala vsjava_finalUrs Peter
 
Java8: what's new and what's hot
Java8: what's new and what's hotJava8: what's new and what's hot
Java8: what's new and what's hotSergii Maliarov
 

Similaire à Java 8 by example! (20)

Java 8 Workshop
Java 8 WorkshopJava 8 Workshop
Java 8 Workshop
 
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
 
Java8
Java8Java8
Java8
 
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...
 
Wien15 java8
Wien15 java8Wien15 java8
Wien15 java8
 
Java 8 - An Overview
Java 8 - An OverviewJava 8 - An Overview
Java 8 - An Overview
 
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
 
FUNctional Programming in Java 8
FUNctional Programming in Java 8FUNctional Programming in Java 8
FUNctional Programming in Java 8
 
Free your lambdas
Free your lambdasFree your lambdas
Free your lambdas
 
Java gets a closure
Java gets a closureJava gets a closure
Java gets a closure
 
Java 8 Intro - Core Features
Java 8 Intro - Core FeaturesJava 8 Intro - Core Features
Java 8 Intro - Core Features
 
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
 
Lambda Functions in Java 8
Lambda Functions in Java 8Lambda Functions in Java 8
Lambda Functions in Java 8
 
java150929145120-lva1-app6892 (2).pptx
java150929145120-lva1-app6892 (2).pptxjava150929145120-lva1-app6892 (2).pptx
java150929145120-lva1-app6892 (2).pptx
 
A Brief Conceptual Introduction to Functional Java 8 and its API
A Brief Conceptual Introduction to Functional Java 8 and its APIA Brief Conceptual Introduction to Functional Java 8 and its API
A Brief Conceptual Introduction to Functional Java 8 and its API
 
Free your lambdas
Free your lambdasFree your lambdas
Free your lambdas
 
Xebicon2013 scala vsjava_final
Xebicon2013 scala vsjava_finalXebicon2013 scala vsjava_final
Xebicon2013 scala vsjava_final
 
Java 8
Java 8Java 8
Java 8
 
Java8: what's new and what's hot
Java8: what's new and what's hotJava8: what's new and what's hot
Java8: what's new and what's hot
 
Functional Programming
Functional ProgrammingFunctional Programming
Functional Programming
 

Dernier

Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...OnePlan Solutions
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsChristian Birchler
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Mater
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxTier1 app
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...Technogeeks
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Velvetech LLC
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Matt Ray
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based projectAnoyGreter
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaHanief Utama
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Angel Borroy López
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Natan Silnitsky
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样umasea
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceBrainSell Technologies
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesŁukasz Chruściel
 
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdfExploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdfkalichargn70th171
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Hr365.us smith
 

Dernier (20)

Advantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your BusinessAdvantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your Business
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
 
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort ServiceHot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...
 
Odoo Development Company in India | Devintelle Consulting Service
Odoo Development Company in India | Devintelle Consulting ServiceOdoo Development Company in India | Devintelle Consulting Service
Odoo Development Company in India | Devintelle Consulting Service
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based project
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief Utama
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. Salesforce
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
 
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdfExploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)
 

Java 8 by example!

  • 1. JAVA 8 - BY EXAMPLE! PATTERNS AND PRACTICES FOR LAMBDAS, STREAMS, OPTIONAL... Createdby /MarkHarrison @markglh
  • 2. INTERFACE DEFAULT METHODS Interfaces can now have default & static methods! Allows new interface methods to be added without breaking existing implementations Multiple inheritance! public interface Comparator<T> { default Comparator<T> reversed() { // Implementation here } public static Comparator<T> naturalOrder() { // Implementation here } }
  • 3. MULTIPLE INHERITANCE... What if a class inherits the same default method from two interfaces??? 1.Class methods always win. Whether it’s this class or the superclass, it will take priority 2.If multiple interfaces de ne the same method with a default implementation, then the most speci c is selected (the child in inheritance terms) 3.If it’s not obvious then the compiler will cry, we need to explicitly choose: INTERFACE.super.METHODNAME
  • 4. LAMBDAS YOU SAY? Basically just a shorthand method implementation Concise and much improved replacement for Anonymous inner classes Makes it easy to pass behaviour around Pass the behaviour into the method, ips the design on its head Lexically scoped (this is effectively shared with the surrounding method)
  • 5. SYNTAX PLEASE! (int x, int y) -> x + y Argument types can be inferred by the compiler: (x, y) -> x + y Zero-arg Lambdas are also possible: () -> "Java 8!" But how can we use them? Consumer<String> inferredConsumer = x -> System.out.println(x);
  • 7. FUNCTIONAL INTERFACES A Functional Interface is any interface with one Single Abstract Method The parameters that the Lambda accepts and returns must match the interface (including exceptions) @FunctionalInterface annotation is provided to highlight these interfaces, it is just a marker though, any SAM interface will work - the annotation simply enforces this at compile time So... When we pass or assign a Lambda: 1. First the Lambda is converted into a Functional Interface 2. Secondly it is invoked via this generated implementation
  • 8. LAMBDA EXAMPLE 1 - PREDICATES Have you ever written code like this? @FunctionalInterface //Added in Java8 public interface Predicate<T> { boolean test(T t); } private void printMatchingPeople( List<Person> people, Predicate<Person> predicate) { for (Person person : people) { if (predicate.test(person)) { System.out.println(person); } } }
  • 9. LAMBDA EXAMPLE 1 - PREDICATES Pre Java 8: public class PersonOver50Predicate implements Predicate<Person> { public boolean test(Person person) { return person.getAge() > 50; } } printMatchingPeople(loadsOfPeople, new PersonOver50Predicate());
  • 10. LAMBDA EXAMPLE 1 - PREDICATES Java 8: printMatchingPeople(loadsOfPeople, x -> x.getAge() > 50); Notice the signature matches that of the Predicate, the compiler automatically gures out the rest What if we had an existing Predicate we wanted to enhance? Composite Predicates FTW... :-) Predicate<Person> ageCheck = x -> x.getAge() > 50; printMatchingPeople(loadsOfPeople, ageCheck.and(x -> x.getIq() > 100));
  • 11. LAMBDA EXAMPLE 2 - RUNNABLE Pre Java 8 mess: Runnable r1 = new Runnable() { @Override public void run() { System.out.println("Meh!"); } }; r1.run(); Java 8: Runnable r = () -> System.out.println("Woop!"); r.run();
  • 12. LAMBDA EXAMPLE 3 - COLLECTIONS Lambdas make lots of new Collection methods possible... List<String> strings = new ArrayList<>(); Collections.addAll(strings, "Java", "7", "FTW"); Do something on every element in the List strings.forEach(x -> System.out.print(x + " ")); //Prints: "Java 7 FTW"
  • 13. LAMBDA EXAMPLE 4 - MORE COLLECTIONS Replace every matching element in the List strings.replaceAll(x -> x == "7" ? "8" : x); strings.forEach(x -> System.out.print(x + " ")); //Prints: "Java 8 FTW" Remove matching elements from the List strings.removeIf(x -> x == "8"); strings.forEach(x -> System.out.print(x + " ")); //Prints: Java FTW
  • 14. LAMBDA EXAMPLE 5 - COMPARATORS @FunctionalInterface //Added in Java8 version public interface Comparator<T> { int compare(T o1, T o2); //Java 8 adds loads of default methods }
  • 15. LAMBDA EXAMPLE 6 - COMPARATORS 2 List<Person> loadsOfPeople = ...; Pre Java 8: public class SortByPersonAge implements Comparator<Person> { public int compare(Person p1, Person p2) { return p1.getAge() - p2.getAge(); } } Collections.sort(loadsOfPeople, new SortByPersonAge()); Java 8: Collections.sort(loadsOfPeople, (p1, p2) -> p1.getAge() - p2.getAge());
  • 16. LAMBDA EXAMPLE 7 - COMPARATORS 3 As usual in Java 8... the Comparator interface provides plenty of useful default & static methods... //"comparing" static method simplifies creation Comparator<Person> newComparator = Comparator.comparing(e -> e.getIq()); //"thenComparing" combines comparators Collections.sort(loadsOfPeople, newComparator.thenComparing( Comparator.comparing(e -> e.getAge())));
  • 17. LAMBDA EXAMPLE 8 - COMPARATORS 4 and more... //More useful Collection methods... loadsOfPeople4.sort( Comparator.comparing(e -> e.getIq())); //And finally... Method references loadsOfPeople.sort( Comparator.comparing(Person::getAge));
  • 18. INTRODUCING METHOD REFERENCES Any method can be automatically “lifted” into a function. It must simply meet contract of the FunctionalInterface Can be easier to debug & test than Lambdas, more descriptive stack traces Promotes re-use, keeping code DRY Uses the "::" syntax
  • 19. METHOD REFERENCES TYPES Reference to... Example a static method Class::staticMethodName an instance method of a speci c object object::instanceMethodName an instance method of an arbitrary object Class::methodName a constructor ClassName::new
  • 20. REFERENCE TO A STATIC METHOD A simple reference to a static method //isPersonOver50 is a static method printMatchingPeople(loadsOfPeople, PersonPredicates::isPersonOver50); This is equivalent to printMatchingPeople(loadsOfPeople, x -> x.getAge() > 50);
  • 21. REFERENCE TO AN INSTANCE METHOD OF A SPECIFIC OBJECT A reference to a method on an object instance List<String> strings = ... //print is a method on the "out" PrintStream object strings.forEach(System.out::print); This is equivalent to strings.forEach(x -> System.out.print(x));
  • 22. REFERENCE TO AN INSTANCE METHOD OF AN ARBITRARY OBJECT Examine this simpli ed de nition of a map function public interface Function<T,R> { public R apply(T t); } public <T, R> List<R> map(Function<T, R> function, List<T> source) { /* applies the function to each element, converting it from T to R */ }
  • 23. REFERENCE TO AN INSTANCE METHOD OF AN ARBITRARY OBJECT CONT... Although it looks like we're referencing a Class method, we're invoking an instance method on the object(s) passed in the call List<Person> loadsOfPeople = ... List<Integer> namesOfPeople = map(Person::getAge, loadsOfPeople); This is equivalent to map(person -> person.getAge(), loadsOfPeople);
  • 24. REFERENCE TO A CONSTRUCTOR Uses the constructor to create new objects, the constructor signature must match that of the @FunctionalInterface List<String> digits = Arrays.asList("1", "2", "3"); //Transforms a String into a new Integer List<Integer> numbers = map(Integer::new, digits); This is equivalent to map(s -> new Integer(s), digits);
  • 25. WHAT'S WRONG WITH COLLECTIONS Every application uses Collections, however Collections are dif cult to query and aggregate, requiring several levels of iteration and conditionals, basically it’s messy and painful Writing multi-threaded code to do this manually is dif cult to write and maintain Imagine writing this manually Stream<String> words=Stream.of("Java", "8", "FTW"); Map<String, Long> letterToNumberOfOccurrences = words.map(w -> w.split("")) .flatMap(Arrays::stream) .collect(Collectors.groupingBy( Function.identity(), Collectors.counting())); //Prints: //{a=2, T=1, F=1, v=1, W=1, 8=1, J=1}
  • 26. INTRODUCING STREAMS! A Stream is a conceptually xed data structure in which elements are computed on demand Streams iterate internally, you don’t have to worry about handling the iteration Pipelining: Akin to the “pipe” command in unix, allowing aggregations to be chained together Automatic optimisation: short-circuiting and lazy processing Can be in nite Can be executed in parallel automatically using parallelStream or parallel()
  • 27. MORE STREAMS... Can be created from multiple sources: Arrays.stream(...), Stream.of(1, 2, 3, 4), Stream.iterate(...), Stream.range(...), Random.ints(), Files.lines(...)... Two types of operations: Intermediate (aggregation): lter, map, atMap, sorted ... Terminal: collect, reduce, forEach, ndAny ... Specialised Streams: IntStream, LongStream and DoubleStream: better performance for those unboxed types
  • 28. MAP public <R> Stream<R> map(Function<T, R> mapper); The mapper Function converts each element from T to R. The result is then added, as is, to the Stream
  • 29. FLATMAP public <R> Stream<R> flatMap(Function<T, Stream<R>> mapper); The mapper Function converts each element from T to a Stream of R This is the key difference to map, the function itself returns a Stream rather than one element This Stream is then attened (merged) into the main Stream To put it another way: atMap lets you replace each value of a Stream with another Stream, and then it concatenates all the generated streams into one single stream
  • 30. REDUCE public T reduce(T identity, BinaryOperator<T> accumulator); public Optional<T> reduce( BinaryOperator<T> accumulator); //This is the function contained in BinaryOperator R apply(T t, U u); Terminal Operation Takes a Stream of values and repeatedly applies the accumulator to reduce them into a single value The accumulator is passed the total so far (T) and the current element (U) If passed, identity provides the initial value, rather than the rst element
  • 31. REDUCE CONTINUED... int totalAgeUsingReduce = loadsOfPeople.stream() .map(Person::getAge) //contains 5, 10, 15 .reduce(0, (total, current) -> total + current); 1.First we map the Person to the age int 2.reduce then starts at 0, and adds the current element, 5 3.reduce continues by adding the current total 5, to the next element, 10 4. nally reduce adds the current total 15, to the next element 15 5.Tada, we've added up all the ages: 30!
  • 32. COLLECTORS The collect method is a terminal operation which takes various "recipes", called Collectors for accumulating the elements of a stream into a summary result, or converting to a speci c type (such as a List) List<String> listOfStrings = loadsOfPeople.stream() .map(x -> x.getName()) .collect(Collectors.toList()); The argument passed to collect is an object of type java .util.stream.Collector It describes how to accumulate the elements of a stream into a nal result Can be used for Grouping, Partitioning, Averaging, ...
  • 33. STREAMS EXAMPLE 1 List<Integer> numbers = Arrays.asList(1, 2 ... 8); List<Integer> twoEvenSquares = numbers.stream() .filter(n -> n % 2 == 0) //Filter odd numbers .map(n -> n * n) ////Multiply by itself .limit(2)//Limit to two results .collect(Collectors.toList()); //Finish! Imagine a println in each step... filtering 1 filtering 2 mapping 2 filtering 3 filtering 4 mapping 4
  • 35. STREAMS EXAMPLE 2 List<String> youngerPeopleSortedByIq = loadsOfPeople.stream() .filter(x -> x.getAge() < 50) .sorted(Comparator .comparing(Person::getIq).reversed()) .map(Person::getName) .collect(Collectors.toList()); 1. Filter out all people older than 50 2. Inverse sort the remaining people by IQ 3. map each person to their name (convert to a Stream<String>) 4. Convert the result to a List
  • 36. STREAMS EXAMPLE 3 - SUM int combinedAge = loadsOfPeople.stream() .mapToInt(Person::getAge) //returns IntStream .sum(); //this HAS to be a specialised Stream 1. map each person to their age, producing an IntStream 2. sum the results, also supports average
  • 37. STREAMS EXAMPLE 4 - MAP, REDUCE String xml = "<people>" + loadsOfPeople.stream() .map(x -> "<person>"+ x.getName() +"</person>") .reduce("", String::concat) //start with "" + "</people>"; map each Person to an XML element (<person>Steve</person>), then use String.concat to reduce the Stream into one XML String <people> <person>Dave</person> <person>Helen</person> <person>Laura</person> <person>Ben</person> </people>
  • 38. STREAMS EXAMPLE 5 - MAP List<Stream<Person>> clonedPeople = loadsOfPeople.stream() .map(person -> Stream.of(person, person.dolly())) .collect(Collectors.toList()); 1.map creates a new Stream containing two people 2.This Stream is then added to the main Stream as-is, leaving us with a pretty useless: List<Stream<Person>>
  • 39. STREAMS EXAMPLE 6 - FLATMAP List<Person> clonedPeople2 = loadsOfPeople.stream() .flatMap(person -> Stream.of(person, person.dolly())) .collect(Collectors.toList()); 1. atMap combines each element from the new Streams into one Stream<Person> 2.So now we've got what we wanted in the rst place, a List<Person> Sweeet!
  • 40. STREAMS EXAMPLE 7 - REDUCE int totalAgeUsingReduce = loadsOfPeople.stream() .map(Person::getAge) .reduce((total, current) -> total + current) .get(); //get the result from the Optional This is the same as the previous example, the difference being we don't specify a default value for reduce Not specifying a default value means the result is Optional... if the Stream is empty then so is the result!
  • 41. STREAMS EXAMPLE 8 - GROUPING Map<Integer, List<Person>> peopleGroupedByAge = loadsOfPeople.stream() .filter(x -> x.getIq() > 110) .collect(Collectors.groupingBy(Person::getAge)); The collect method groups the ltered results by age, producing a Map<age, <Person>> {52=[Person{... age=52, iq=113, gender=MALE}], 60=[Person{... age=60, iq=120, gender=FEMALE}], 28=[Person{... age=28, iq=190, gender=MALE}]}
  • 42. STREAMS EXAMPLE 9 - PARTITIONING Map<Boolean, List<Person>> peoplePartitionedByAge = loadsOfPeople.stream().filter(x -> x.getIq() > 110) .collect(Collectors .partitioningBy(x -> x.getAge() > 55)); The collect method partitions the ltered results by age The Map will have two entries, true and false, according to the Predicate {false=[Person{... age=28, iq=190, gender=MALE}], true=[Person{... age=60, iq=120, gender=FEMALE}]}
  • 43. STREAMS EXAMPLE 10 - MULTIPLE GROUPS Map<Integer, Double> peopleGroupedBySexAndAvgAge = loadsOfPeople.stream() .filter(x -> x.getIq() > 110) .collect( Collectors.groupingBy(Person::getAge, Collectors.averagingInt(Person::getIq))); We can group by multiple Collectors Here we group by age and the average IQ of that group {52=113.0, 60=117.5, 28=190.0}
  • 44. STREAMS EXAMPLE 11 - FINDANY loadsOfPeople.stream() .filter(t -> t.getGender() == Person.Sex.FEMALE) .findAny() .ifPresent(System.out::println); findAny either returns an element or nothing, hence we get an Optional ifPresent executes the Lambda if we get a result
  • 45. STREAMS EXAMPLE 12 - PARALLEL Lets iterate over 10,000,000 elements! x -> Stream.iterate(1L, i -> i + 1) .limit(x) .reduce(Long::sum).get(); Executes in 80ms - we incur a penalty here because the long is repeatedly boxed and unboxed Executes in 211ms?! It turns out parallel isn't always a free win! x -> Stream.iterate(1L, i -> i + 1) .parallel().limit(x) .reduce(Long::sum).get();
  • 46.
  • 47. STREAMS EXAMPLE 13 - PARALLEL WIN! x -> LongStream.rangeClosed(1L, x) .reduce(Long::sum).getAsLong(); Executes in 24ms - much better using an unboxed Stream Executes in 7ms - now that the Stream isn't dynamic, parallel works much better! x -> LongStream.rangeClosed(1L, x) .parallel() .reduce(Long::sum).getAsLong();
  • 48. OPTIONAL Use Optional instead of passing null around, helps prevent NullPointerExceptions Optional is a container that’s either empty or present, in which case it contains a value So anytime that you’re thinking of return or accepting a null value in a method, use Optional instead! public class Computer { private Optional<Mainboard> mainboard; } public class Mainboard { private Optional<Cpu> cpu; } public class Cpu { private String type; }
  • 49. USING OPTIONAL Several ways to create an Optional: Optional.of(cpu); //Throws an NPE if cpu is null Optional.ofNullable(cpu); //empty if cpu is null Getting the contents from the Optional: cpu.get(); //get CPU or throw NoSuchElementException cpu.orElse(new Cpu()); //safe get, provides default And more... cpu.isPresent(); //true if present, false if empty cpu.ifPresent(x -> System.out.println(x.getType())); Also supports map, atMap and lter!
  • 50. OPTIONAL EXAMPLE 1 - BASICS if (mainboard.isPresent() && mainboard.get().getCpu().isPresent()) { mainboard.get().getCpu().get().getType(); } Eww! Lets try something else! ***Fails to compile, calling getType on an Optional... if only we could atten it??? Optional<String> cpuType = mainboard.map(Mainboard::getCpu) .map(Cpu::getType); //Optional<Optional<Cpu>>
  • 51. OPTIONAL EXAMPLE 2 - FLATMAP Optional<String> stringOptional = mainboard .flatMap(Mainboard::getCpu) .map(Cpu::getType); Lets take this further and safely get cpu type of a Computer! Computer computer = new Computer(mainboard); String cpu = computer.getMainboard() .flatMap(Mainboard::getCpu) .map(Cpu::getType) .filter(x -> "Intel".equals(x)) .orElse("Nothing we're interested in!");
  • 52. IT'S BEEN EMOTIONAL... Slides at Source at Follow me markglh.github.io/Java8Madlab-Slides github.com/markglh/Java8Madlab-Examples @markglh
  • 53. RECOMMENDED READING Lambdas Part 1 (Ted Neward) Lambdas Part 2 (Ted Neward) Lambda Expressions vs Method References (Edwin Dalorzo) Youtube: Java 8 - more readable and exible code (Raoul- Gabriel Urma) Youtube: Lambda Expressions & Streams (Adib Saikali) Java 8 Streams Part 1 (Raoul-Gabriel Urma) Java 8 Streams Part 2 (Raoul-Gabriel Urma) Optional - No more NPE's (Raoul-Gabriel Urma)