SlideShare a Scribd company logo
1
Ready for
"Functional Programming"
with Java 8 ?
Yanai Franchi , Tikal
2
Agenda
● First-Class Functions
● FP with Streams
● Working Concurrency
● Demo
3
First Class Functions
4
Our Inventory = List of Apples
5
Class Apple
● getColor() : String
● getWeight() : int
6
Green Apples, Please...
7
Green Apples, Please...
8
Filter Green Apples
public static List<Apple> filterGreenApples(List<Apple> inventory){
List<Apple> result = new ArrayList<>();
for (Apple apple: inventory){
if (apple.getColor().equals(“green”)) {
result.add(apple);
}
}
return result;
}
Starts empty,
add green apples
one by one
Select only green apples
9
Now Heavy Ones , Please...
10
Easy...We Copy&Paste :(
public static List<Apple> filterHeavyApples(List<Apple> inventory){
List<Apple> result = new ArrayList<>();
for (Apple apple: inventory){
if (apple.getWeight() > 150) {
result.add(apple);
}
}
return result;
}
We only change
the predicate
11
What's the Difference ?
public static List<Apple> filterGreenApples
(List<Apple> inventory){
List<Apple> result = new ArrayList<>();
for (Apple apple: inventory){
if (apple.getColor.equals(“green”)) {
result.add(apple);
}
}
return result;
}
public static List<Apple> filterHeavyApples
(List<Apple> inventory){
List<Apple> result = new ArrayList<>();
for (Apple apple: inventory){
if (apple.getWeight() > 150) {
result.add(apple);
}
}
return result;
}
12
13
New Behavior
Behavior
Parameterization
Output
apple.getWeight > 150 apple.getColor.equals(“green”)
Heavy Apples Green Apples
static List<Apple> filterApples(
List<Apple> inventory, Predicate<Apple> p) {
List<Apple> result = new ArrayList<>();
for (Apple apple: inventory){
if (p.test(apple)) {
result.add(apple);
}
}
return result;
}
14
In Practice, Our Client...Yuck :(
List<Apple> greenApples =
filterApples(inventory,new Predicate<Apple>() {
@Override
public boolean test(Apple a) {
return a.getColor().equals(“green”);
}
});
A lot of “noise”
15
16
Java8 Lambda to Rescue
filterApples(inventory,
(Apple a) → {return a.getColor().equals(“green”)});
17
Sending Lambda Expression
filterApples(inventory,
(Apple a) → a.getColor().equals(“green”));
18
Making it Shorter
filterApples(inventory,
(a) → a.getColor().equals(“green”));
Apple Type is
Inferred
19
...Even Shorter
filterApples(inventory,
a → a.getColor().equals(“green”));
20
“Capture” Values (a.k.a “Closure”)
String color = “green”;
filterApples(inventory,
a → a.getColor().equals(color));
Implicitly final
21
22
Anonymous Function that Can Be
Passed Around
filterApples(inventory,
a → a.equals.getColor(“green”));
23
Switch to Method Reference
filterApples(inventory,a → a.equals.getColor(“green”));
24
Switch to Method Reference
filterApples(inventory,Apple::isGreen);
filterApples(inventory,a → a.getColor().equals(“green”));
isGreen is
declared in Apple
25
Until Now...
26
...In Java 8
27
Lambda Type = Functional Interface
Predicate<Apple> redApple = a → a.getColor().equals(“red”);
Predicate is the
type of our lambda
28
Meet Functional Interface
@FunctionalInterface
public interface Predicate<T>{
boolean test(T t);
}
Just Marker
● Definition: a
functional interface is
an interface with one
abstract method
● Single Abstract
Method (SAM) type
SAM
29
Default Methods
Implementations in Interface
@FunctionalInterface
public interface Predicate<T>{
boolean test(T t);
default Predicate<T> negate(){
return (t) -> !test(t);
}
default or(Predicate<? super T> other){
return (t) -> test(t) ||
other.test(t);
}
default and(Predicate<? super T> other){
return (t) -> test(t) &&
other.test(t);
}
}
Default Method
30
Existing Function Interfaces
interface Comparator<T> { boolean compare(T x, T y); }
(int x, int y) → x - y ;
interface FileFilter { boolean accept(File x); }
f → f.isDirectory()
interface Runnable { void run(); }
() → someCode();
interface ActionListener{ void actionPerformed(ActionEvent ae); }
(ae -> log.debug(“Got it!”));
31
New Function Interfaces
● Predicate<T> : boolean test(T t);
– Determine if the input of type T matches some criteria :
● Consumer<T> : void accept(T t);
– Accept a single input argument of type T, and return no
result :
● Supplier<T> : T get();
– A factory that’s expected to return either a new instance
or a pre-created instance :
● Function<T, R> : R apply(T t);
– Apply a function to the input type T, generating a result
of type R
32
33
Sorting with Anonymous Class
inventory.sort(new Comparator<Apple>() {
public int compare(Apple a1, Apple a2){
return a1.getWeight().compareTo(a2.getWeight());
}
});
High Order
Function
34
Sort with Lambda
inventory.sort(
(a1,a2) → a1.getWeight().compareTo(a2.getWeight())
);
35
Using “comparing” Method
Comparator Interface
Static method
inventory.sort(comparing(Apple::getWeight));
Static method that accept
Function and return Comparator
36
FP with Streams
37
Dish
Row 1 Row 2 Row 3 Row 4
0
2
4
6
8
10
12
Column 1
Column 2
Column 3
● String getName()
● boolean isVegeterian()
● int getCalories()
● Type getType()
● List<String> getNickNames()
● CaloricLevel getCaloricLevel()
38
Three Fat Dishes - Imperative
● Client controls iteration
● Inherently serial: iterate
from beginning to end
● Not thread-safe because
business logic is stateful
(mutable accumulator
variable)
● Frustratingly imperative
List<String> fatsDishes = ...
int count = 0;
for(Dish d : menu){
if (count > 3)
break;
if(d.getCalories > 300){
count++;
fatsDishes.add(d.getName());
}
}
External
Iteration
39
40
FP → Declarative Code
List<String> fatDishes =
menu.stream()
.filter(d -> d.getCalories() > 300)
.map(Dish::getName)
.limit(3)
.collect(toList());
41
42
But What is a Stream ?
● A sequence of elements from a source that
supports aggregate operations
– Aimed for computations and aggregations (In
contrary to collections which are data structures)
– Consume from a data-providing source such as
Collections, Arrays, or IO resources.
– Support SQL-like operations and common
operations from functional programing languages
such as filter, map, reduce, find, match, sorted etc.
43
Creating Stream
● IntStream.range(1, 100)
● Stream.of("Java 8 ", "Lambdas");
● File.list(Paths.get("some-folder"))
● Files.lines(Paths.get("data.txt"))
● myList.parallelStream()
● Create infinite stream
– Iterate
● Stream.iterate(0, n -> n + 2)
● Stream.iterate(new int[]{0, 1}, t -> new int[]{t[1], t[0]+t[1]})
– Stream.generate(Math::random)
44
High Order Function - map
● <R> Stream<R>
map(Function<? super T, ? extends R> mapper);
● Apply the mapper function on each element of
the stream , and create a new stream from its
outputs by placing the results of the mapper on
the new stream
● map(Dish::getName). Converts a Stream of
dishes to Stream names (Strings), by applying
Dish.getName() on the elements.
45
High Order Function - flatMap
●
<R> Stream<R>
flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
● Apply the mapper function on each element of
the stream and create a new stream from its
outputs, by placing contents of the mapped
streams in the new stream
● menu.stream().flatMap(d → d.getNickNames().stream())
– Converts a Stream of dishes to Stream of
nickNames (String), by replacing all nicknames as
elements of the stream.
46
Limit - “Short Circuit”
List<String> names = menu.stream()
.filter(d -> {System.out.println("filtering" + d);
return d.getCalories() > 300;})
.map(d -> {System.out.println("mapping" + d);
return d.getName();})
.limit(3)
.collect(toList());
filtering pork
mapping pork
filtering beef
filtering chicken
mapping chicken
filtering egg
filtering spaghetti
mapping spaghetti
Short Circuit:
Stopped printing
after 3 dishes
47
Finding & Matching - “Short Circuit”
● No need to process the whole stream
● As soon as an element is found a result can be
produced.
● Finding Operations:
– anyMatch, noneMatch, findFirst and findAny
boolean found =
menu.stream().anyMatch(Dish::isVegatarian)
48
Group Dishes by Type - Imperative
Map<Dish.Type, List<Dish>> groupDishesByTypeMap =
new HashMap<>();
for (Dish dish : menu) {
final Type type = dish.getType();
List<Dish> dishesForType = groupDishesByTypeMap.get(type);
if(dishesForType == null){
dishesForType = new ArrayList<>();
groupDishesByTypeMap.put(type, dishesForType);
}
dishesForType.add(dish);
}
return groupDishesByTypeMap;
49
Grouping with FP - Declarative
Map<Dish.Type, List<Dish>> groupDishesByTypeMap =
menu.stream().collect(groupingBy(Dish::getType));
Collectors static method
50
Count Dishes Per Type
Map<Dish.Type, Long> typesCount =
menu.stream().collect(
groupingBy(Dish::getType,counting()));
{MEAT=3, FISH=2, OTHER=4}
Output
Collectors static method
51
One More Level...
52
One More Level...
Map<Dish.Type, Map<CaloricLevel, List<Dish>>>
groupDishesByTypeAndCaloricLevel =
menu.stream()
.collect(groupingBy(
Dish::getType,
groupingBy(Dish::getCaloricLevel)));
{
MEAT={DIET=[chicken], NORMAL=[beef], FAT=[pork]},
FISH={DIET=[prawns], NORMAL=[salmon]},
OTHER={DIET=[rice, seasonal fruit], NORMAL=[french fries, pizza]}
}
Output
53
Working Concurrency
54
Process Dishes in Parallel
● Uses the ForkJoin framework behind the scenes
● By Default number of threads is as the number of
processors
● Will NOT keep the original order of the stream
menu.parallelStream().forEach(Dish::heavyCalculation);
55
Total Calories in Menu – Imperative
int i=0;
for (Dish dish : menu) {
i += dish.getCalories();
}
Side Effect
56
We Know What To Do...
● The only difference is the reduction function
● For min, max, avg etc – The code will look the
same
int i=0;
for (Dish dish : menu) {
i += dish.getCalories();
}
int i=0;
for (Dish dish : menu) {
i = Math.max(dish.getCalories(),i);
}
57
Move To FP – Bad Way :(
Accumulator accumulator = new Accumulator();
menu.stream()
.map(Dish::getCalories)
.forEach(accumulator::add);
accumulator.getTotal();
class Accumulator {
private long total = 0;
long getTotal(){return total);
public void add(long value) {
total += value;
}
} Side Effect
58
Break Concurrency!!! :(
Accumulator accumulator = new Accumulator();
menu.parallelStream()
.map(Dish::getCalories)
.forEach(accumulator::add)
accumulator.getTotal();
Different result
For the same input
59
Reducing
Row 1 Row 2 Row 3 Row 4
0
2
4
6
8
10
12
Column 1
Column 2
Column 3
menu.parallelStream()
.map(Dish::getCalories)
.sum();
menu.parallelStream()
.map(Dish::getCalories)
.reduce(0,Integer:sum);
=
60
FP - Data is Immutable
● Once object is created, it can't be changed.
● If you need to change an object, make a copy.
– Enables concurrency
– Rollback of data
– Simplicity
61
Mutable Tree – What's Wrong ?
class Tree {
private String key;
private int val;
private Tree left, right;
public Tree(String k, int v, Tree l, Tree r) {
key = k; val = v; left = l; right = r;
}
}
public static Tree update(String k, int newval, Tree t) {
if (t == null)
t = new Tree(k, newval, null, null);
else if (k.equals(t.key))
t.val = newval;
else if (k.compareTo(t.key) < 0)
t.left = update(k, newval, t.left);
else
t.right = update(k, newval, t.right);
return t;
}
62
Concurrency Problems
● Every user wants to share the identical data
structure and see updates caused by any part
of the program.
● Hence it is vital (but often overlooked) in
nonfunctional code that whenever we add some
form of structured value to a tree then we copy
it - Who knows, someone may later assume
they can update it.
● In Functional approach – Share storage for
common parts of structure.
63
Marry
22
Emily
20 Titan
29
Alan
50
Georgie
23
Raoul
25
Persistent Tree
64
Marry
22
Emily
20 Titan
29
Alan
50
Georgie
23
Raoul
25
Input : “will”, 26
Persistent Tree
65
Marry
22
Emily
20 Titan
29
Alan
50
Georgie
23
Raoul
25
Marry
22
Titan
29
Will
26
Output of updateInput : “will”, 26
Persistent Tree
66
Persistent Tree
class Tree {
private String key;
private int val;
private Tree left, right;
public Tree(String k, int v, Tree l, Tree r) {
key = k; val = v; left = l; right = r;
}
}
public static Tree fupdate(String k, int newval, Tree t) {
return (t == null) ?
new Tree(k, newval, null, null) :
k.equals(t.key) ?
new Tree(k, newval, t.left, t.right) :
k.compareTo(t.key) < 0 ?
new Tree(t.key, t.val, fupdate(k,newval, t.left), t.right) :
new Tree(t.key, t.val, t.left, fupdate(k,newval, t.right));
}
67
Analyze Multiple Apache Logs
68
Analyze Multiple Apache Logs
● Host, Time, Request, Response, Resp-Length
199.72.81.55 - - [02/Jul/1995:00:00:01 -0400] "GET /history/apollo/ HTTP/1.0" 200 6245
unicomp6.unicomp.net - - [02/Jul/1995:00:00:06 -0400] "GET /shuttle/countdown/ HTTP/1.0" 200 3985
199.120.110.21 - - [01/Jul/1995:00:00:09 -0400] "GET /shuttle/missions/sts-73/mission-sts-73.html HTTP/1.0" 200 4085
burger.letters.com - - [01/Jul/1995:00:00:11 -0400] "GET /shuttle/countdown/liftoff.html HTTP/1.0" 304 0
199.120.110.21 - - [01/Jul/1995:00:00:11 -0400] "GET /shuttle/missions/sts-73/sts-73-patch-small.gif HTTP/1.0" 200 4179
burger.letters.com - - [01/Jul/1995:00:00:12 -0400] "GET /images/NASA-logosmall.gif HTTP/1.0" 304 0
burger.letters.com - - [01/Jul/1995:00:00:12 -0400] "GET /shuttle/countdown/video/livevideo.gif HTTP/1.0" 200 0
205.212.115.106 - - [01/Jul/1995:00:00:12 -0400] "GET /shuttle/countdown/countdown.html HTTP/1.0" 200 3985
d104.aa.net - - [01/Jul/1995:00:00:13 -0400] "GET /shuttle/countdown/ HTTP/1.0" 200 3985
129.94.144.152 - - [01/Jul/1995:00:00:13 -0400] "GET / HTTP/1.0" 200 7074
unicomp6.unicomp.net - - [01/Jul/1995:00:00:14 -0400] "GET /shuttle/countdown/count.gif HTTP/1.0" 200 40310
unicomp6.unicomp.net - - [01/Jul/1995:00:00:14 -0400] "GET /images/NASA-logosmall.gif HTTP/1.0" 200 786
unicomp6.unicomp.net - - [01/Jul/1995:00:00:14 -0400] "GET /images/KSC-logosmall.gif HTTP/1.0" 200 1204
d104.aa.net - - [01/Jul/1995:00:00:15 -0400] "GET /shuttle/countdown/count.gif HTTP/1.0" 200 40310
d104.aa.net - - [01/Jul/1995:00:00:15 -0400] "GET /images/NASA-logosmall.gif HTTP/1.0" 200 786
d104.aa.net - - [01/Jul/1995:00:00:15 -0400] "GET /images/KSC-logosmall.gif HTTP/1.0" 200 1204
129.94.144.152 - - [01/Jul/1995:00:00:17 -0400] "GET /images/ksclogo-medium.gif HTTP/1.0" 304 0
199.120.110.21 - - [01/Jul/1995:00:00:17 -0400] "GET /images/launch-logo.gif HTTP/1.0" 200 1713
ppptky391.asahi-net.or.jp - - [01/Jul/1995:00:00:18 -0400] "GET /facts/about_ksc.html HTTP/1.0" 200 3977
ppptky391.asahi-net.or.jp - - [01/Jul/1995:00:00:19 -0400] "GET /images/launchpalms-small.gif HTTP/1.0" 200 11473
205.189.154.54 - - [01/Jul/1995:00:00:24 -0400] "GET /shuttle/countdown/ HTTP/1.0" 200 3985
…
...
199.72.81.55 - - [02/Jul/1995:00:00:01 -0400] "GET /history/apollo/ HTTP/1.0" 200 6245
unicomp6.unicomp.net - - [02/Jul/1995:00:00:06 -0400] "GET /shuttle/countdown/ HTTP/1.0" 200 3985
199.120.110.21 - - [01/Jul/1995:00:00:09 -0400] "GET /shuttle/missions/sts-73/mission-sts-73.html HTTP/1.0" 200 4085
burger.letters.com - - [01/Jul/1995:00:00:11 -0400] "GET /shuttle/countdown/liftoff.html HTTP/1.0" 304 0
199.120.110.21 - - [01/Jul/1995:00:00:11 -0400] "GET /shuttle/missions/sts-73/sts-73-patch-small.gif HTTP/1.0" 200 4179
burger.letters.com - - [01/Jul/1995:00:00:12 -0400] "GET /images/NASA-logosmall.gif HTTP/1.0" 304 0
burger.letters.com - - [01/Jul/1995:00:00:12 -0400] "GET /shuttle/countdown/video/livevideo.gif HTTP/1.0" 200 0
205.212.115.106 - - [01/Jul/1995:00:00:12 -0400] "GET /shuttle/countdown/countdown.html HTTP/1.0" 200 3985
d104.aa.net - - [01/Jul/1995:00:00:13 -0400] "GET /shuttle/countdown/ HTTP/1.0" 200 3985
129.94.144.152 - - [01/Jul/1995:00:00:13 -0400] "GET / HTTP/1.0" 200 7074
unicomp6.unicomp.net - - [01/Jul/1995:00:00:14 -0400] "GET /shuttle/countdown/count.gif HTTP/1.0" 200 40310
unicomp6.unicomp.net - - [01/Jul/1995:00:00:14 -0400] "GET /images/NASA-logosmall.gif HTTP/1.0" 200 786
unicomp6.unicomp.net - - [01/Jul/1995:00:00:14 -0400] "GET /images/KSC-logosmall.gif HTTP/1.0" 200 1204
d104.aa.net - - [01/Jul/1995:00:00:15 -0400] "GET /shuttle/countdown/count.gif HTTP/1.0" 200 40310
d104.aa.net - - [01/Jul/1995:00:00:15 -0400] "GET /images/NASA-logosmall.gif HTTP/1.0" 200 786
d104.aa.net - - [01/Jul/1995:00:00:15 -0400] "GET /images/KSC-logosmall.gif HTTP/1.0" 200 1204
129.94.144.152 - - [01/Jul/1995:00:00:17 -0400] "GET /images/ksclogo-medium.gif HTTP/1.0" 304 0
199.120.110.21 - - [01/Jul/1995:00:00:17 -0400] "GET /images/launch-logo.gif HTTP/1.0" 200 1713
ppptky391.asahi-net.or.jp - - [01/Jul/1995:00:00:18 -0400] "GET /facts/about_ksc.html HTTP/1.0" 200 3977
ppptky391.asahi-net.or.jp - - [01/Jul/1995:00:00:19 -0400] "GET /images/launchpalms-small.gif HTTP/1.0" 200 11473
205.189.154.54 - - [01/Jul/1995:00:00:24 -0400] "GET /shuttle/countdown/ HTTP/1.0" 200 3985
…
...
199.72.81.55 - - [02/Jul/1995:00:00:01 -0400] "GET /history/apollo/ HTTP/1.0" 200 6245
unicomp6.unicomp.net - - [02/Jul/1995:00:00:06 -0400] "GET /shuttle/countdown/ HTTP/1.0" 200 3985
199.120.110.21 - - [01/Jul/1995:00:00:09 -0400] "GET /shuttle/missions/sts-73/mission-sts-73.html HTTP/1.0" 200 4085
burger.letters.com - - [01/Jul/1995:00:00:11 -0400] "GET /shuttle/countdown/liftoff.html HTTP/1.0" 304 0
199.120.110.21 - - [01/Jul/1995:00:00:11 -0400] "GET /shuttle/missions/sts-73/sts-73-patch-small.gif HTTP/1.0" 200 4179
burger.letters.com - - [01/Jul/1995:00:00:12 -0400] "GET /images/NASA-logosmall.gif HTTP/1.0" 304 0
burger.letters.com - - [01/Jul/1995:00:00:12 -0400] "GET /shuttle/countdown/video/livevideo.gif HTTP/1.0" 200 0
205.212.115.106 - - [01/Jul/1995:00:00:12 -0400] "GET /shuttle/countdown/countdown.html HTTP/1.0" 200 3985
d104.aa.net - - [01/Jul/1995:00:00:13 -0400] "GET /shuttle/countdown/ HTTP/1.0" 200 3985
129.94.144.152 - - [01/Jul/1995:00:00:13 -0400] "GET / HTTP/1.0" 200 7074
unicomp6.unicomp.net - - [01/Jul/1995:00:00:14 -0400] "GET /shuttle/countdown/count.gif HTTP/1.0" 200 40310
unicomp6.unicomp.net - - [01/Jul/1995:00:00:14 -0400] "GET /images/NASA-logosmall.gif HTTP/1.0" 200 786
unicomp6.unicomp.net - - [01/Jul/1995:00:00:14 -0400] "GET /images/KSC-logosmall.gif HTTP/1.0" 200 1204
d104.aa.net - - [01/Jul/1995:00:00:15 -0400] "GET /shuttle/countdown/count.gif HTTP/1.0" 200 40310
d104.aa.net - - [01/Jul/1995:00:00:15 -0400] "GET /images/NASA-logosmall.gif HTTP/1.0" 200 786
d104.aa.net - - [01/Jul/1995:00:00:15 -0400] "GET /images/KSC-logosmall.gif HTTP/1.0" 200 1204
129.94.144.152 - - [01/Jul/1995:00:00:17 -0400] "GET /images/ksclogo-medium.gif HTTP/1.0" 304 0
199.120.110.21 - - [01/Jul/1995:00:00:17 -0400] "GET /images/launch-logo.gif HTTP/1.0" 200 1713
ppptky391.asahi-net.or.jp - - [01/Jul/1995:00:00:18 -0400] "GET /facts/about_ksc.html HTTP/1.0" 200 3977
ppptky391.asahi-net.or.jp - - [01/Jul/1995:00:00:19 -0400] "GET /images/launchpalms-small.gif HTTP/1.0" 200 11473
205.189.154.54 - - [01/Jul/1995:00:00:24 -0400] "GET /shuttle/countdown/ HTTP/1.0" 200 3985
…
...
69
Requirements
● Answer the following:
– Are there any errors ?
– Are there any empty-body responses ?
– Find last 5 error
– Count statuses for each day
● Assumptions
– Analyze multiple logs in “logs” folder
– Logs files are big and can't fit into memory
70
Design
● LogEntry - Entity Class
– parse(String line) : LogEntry
● LogAnalyticService – Service Class
– streamLogs() : Stream<LogEntry>
● Stream log files in folder
● Per Each file Stream lines
● Map each line to LogEntry
● anyMatch – Reuse for different predicates
● groupBy – For grouping
71
Implementation
private Stream<LogEntry> streamLogs() {
try {
return
Files.list(Paths.get(loggingDir))
.filter(p -> p.getFileName().endsWith(LOG_EXT))
.flatMap(Files::lines)
.map(LogEntry::parse);
} catch (final Exception e) {
throw new RuntimeException(e);
}
}
Will not Compile
72
private Stream<LogEntry> streamLogs() {
try {
return
Files.list(Paths.get(loggingDir))
.filter(p -> p.getFileName().endsWith(LOG_EXT))
.flatMap(this::lines)
.map(LogEntry::parse);
} catch (final Exception e) {
throw new RuntimeException(e);
}
}
private Stream<String> lines(final Path path) {
try {
return Files.lines(path);
} catch (IOException e) {
logger.error("Failed to process "+path,e);
return Stream.empty();
}
}
73
Last Err Logs
return streamLogs()
.filter((le) -> le.getResponse() >= 500)
.sorted(comparing(LogEntry::getDateTime).reversed())
.limit(5)
.collect(toList());
74
Sending Predicates
public boolean isAnyWithResponse(int response) {
return anyMatch((le) -> le.getResponse() == response);
}
public boolean isAnyEmptyResponse() {
return anyMatch((le) -> le.getByteSent() == 0);
}
boolean anyMatch(Predicate<? super LogEntry> predicate) {
return streamLogs().anyMatch(predicate);
}
75
Grouping Results
Map<LocalDate, Map<Integer, Long>> groupingByDatesThenResponse() {
return
streamLogs()
.collect(groupingBy(
LogEntry::getDate,
TreeMap::new,
groupingBy(LogEntry::getResponse, counting()))
);
}
Ordered Keys
Nested Grouping
76
Let's Run it...
77
FP Summary
● Functions are first-class citizens
– Can be declared as variables, pass as arguments
or be returned by other functions
● Declarative instead of imperative
– We tell what to do, instead of how
● Data Immutability
– Reduce Side Effect
– Easier path to parallel code
● Java 8 Lambda & Streams enable FP style
78
Thank you
Ad

More Related Content

What's hot (20)

The Ring programming language version 1.2 book - Part 23 of 84
The Ring programming language version 1.2 book - Part 23 of 84The Ring programming language version 1.2 book - Part 23 of 84
The Ring programming language version 1.2 book - Part 23 of 84
Mahmoud Samir Fayed
 
Programmation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScriptProgrammation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScript
Loïc Knuchel
 
PHP and MySQL Tips and tricks, DC 2007
PHP and MySQL Tips and tricks, DC 2007PHP and MySQL Tips and tricks, DC 2007
PHP and MySQL Tips and tricks, DC 2007
Damien Seguy
 
The Ring programming language version 1.5.4 book - Part 34 of 185
The Ring programming language version 1.5.4 book - Part 34 of 185The Ring programming language version 1.5.4 book - Part 34 of 185
The Ring programming language version 1.5.4 book - Part 34 of 185
Mahmoud Samir Fayed
 
Lists
ListsLists
Lists
Lakshmi Sarvani Videla
 
JAVA 8 : Migration et enjeux stratégiques en entreprise
JAVA 8 : Migration et enjeux stratégiques en entrepriseJAVA 8 : Migration et enjeux stratégiques en entreprise
JAVA 8 : Migration et enjeux stratégiques en entreprise
SOAT
 
Python Workshop Part 2. LUG Maniapl
Python Workshop Part 2. LUG ManiaplPython Workshop Part 2. LUG Maniapl
Python Workshop Part 2. LUG Maniapl
Ankur Shrivastava
 
20170509 rand db_lesugent
20170509 rand db_lesugent20170509 rand db_lesugent
20170509 rand db_lesugent
Prof. Wim Van Criekinge
 
The Ring programming language version 1.9 book - Part 42 of 210
The Ring programming language version 1.9 book - Part 42 of 210The Ring programming language version 1.9 book - Part 42 of 210
The Ring programming language version 1.9 book - Part 42 of 210
Mahmoud Samir Fayed
 
Javascript
JavascriptJavascript
Javascript
Vlad Ifrim
 
Model-Driven Software Development - Static Analysis & Error Checking
Model-Driven Software Development - Static Analysis & Error CheckingModel-Driven Software Development - Static Analysis & Error Checking
Model-Driven Software Development - Static Analysis & Error Checking
Eelco Visser
 
The Ring programming language version 1.5.1 book - Part 32 of 180
The Ring programming language version 1.5.1 book - Part 32 of 180The Ring programming language version 1.5.1 book - Part 32 of 180
The Ring programming language version 1.5.1 book - Part 32 of 180
Mahmoud Samir Fayed
 
An introduction to functional programming with go
An introduction to functional programming with goAn introduction to functional programming with go
An introduction to functional programming with go
Eleanor McHugh
 
Swift에서 꼬리재귀 사용기 (Tail Recursion)
Swift에서 꼬리재귀 사용기 (Tail Recursion)Swift에서 꼬리재귀 사용기 (Tail Recursion)
Swift에서 꼬리재귀 사용기 (Tail Recursion)
진성 오
 
Python Programming Essentials - M12 - Lists
Python Programming Essentials - M12 - ListsPython Programming Essentials - M12 - Lists
Python Programming Essentials - M12 - Lists
P3 InfoTech Solutions Pvt. Ltd.
 
dotSwift 2016 : Beyond Crusty - Real-World Protocols
dotSwift 2016 : Beyond Crusty - Real-World ProtocolsdotSwift 2016 : Beyond Crusty - Real-World Protocols
dotSwift 2016 : Beyond Crusty - Real-World Protocols
Rob Napier
 
7 Habits For a More Functional Swift
7 Habits For a More Functional Swift7 Habits For a More Functional Swift
7 Habits For a More Functional Swift
Jason Larsen
 
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kirill Rozov
 
Python programming : Arrays
Python programming : ArraysPython programming : Arrays
Python programming : Arrays
Emertxe Information Technologies Pvt Ltd
 
The Ring programming language version 1.5.3 book - Part 34 of 184
The Ring programming language version 1.5.3 book - Part 34 of 184The Ring programming language version 1.5.3 book - Part 34 of 184
The Ring programming language version 1.5.3 book - Part 34 of 184
Mahmoud Samir Fayed
 
The Ring programming language version 1.2 book - Part 23 of 84
The Ring programming language version 1.2 book - Part 23 of 84The Ring programming language version 1.2 book - Part 23 of 84
The Ring programming language version 1.2 book - Part 23 of 84
Mahmoud Samir Fayed
 
Programmation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScriptProgrammation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScript
Loïc Knuchel
 
PHP and MySQL Tips and tricks, DC 2007
PHP and MySQL Tips and tricks, DC 2007PHP and MySQL Tips and tricks, DC 2007
PHP and MySQL Tips and tricks, DC 2007
Damien Seguy
 
The Ring programming language version 1.5.4 book - Part 34 of 185
The Ring programming language version 1.5.4 book - Part 34 of 185The Ring programming language version 1.5.4 book - Part 34 of 185
The Ring programming language version 1.5.4 book - Part 34 of 185
Mahmoud Samir Fayed
 
JAVA 8 : Migration et enjeux stratégiques en entreprise
JAVA 8 : Migration et enjeux stratégiques en entrepriseJAVA 8 : Migration et enjeux stratégiques en entreprise
JAVA 8 : Migration et enjeux stratégiques en entreprise
SOAT
 
Python Workshop Part 2. LUG Maniapl
Python Workshop Part 2. LUG ManiaplPython Workshop Part 2. LUG Maniapl
Python Workshop Part 2. LUG Maniapl
Ankur Shrivastava
 
The Ring programming language version 1.9 book - Part 42 of 210
The Ring programming language version 1.9 book - Part 42 of 210The Ring programming language version 1.9 book - Part 42 of 210
The Ring programming language version 1.9 book - Part 42 of 210
Mahmoud Samir Fayed
 
Model-Driven Software Development - Static Analysis & Error Checking
Model-Driven Software Development - Static Analysis & Error CheckingModel-Driven Software Development - Static Analysis & Error Checking
Model-Driven Software Development - Static Analysis & Error Checking
Eelco Visser
 
The Ring programming language version 1.5.1 book - Part 32 of 180
The Ring programming language version 1.5.1 book - Part 32 of 180The Ring programming language version 1.5.1 book - Part 32 of 180
The Ring programming language version 1.5.1 book - Part 32 of 180
Mahmoud Samir Fayed
 
An introduction to functional programming with go
An introduction to functional programming with goAn introduction to functional programming with go
An introduction to functional programming with go
Eleanor McHugh
 
Swift에서 꼬리재귀 사용기 (Tail Recursion)
Swift에서 꼬리재귀 사용기 (Tail Recursion)Swift에서 꼬리재귀 사용기 (Tail Recursion)
Swift에서 꼬리재귀 사용기 (Tail Recursion)
진성 오
 
dotSwift 2016 : Beyond Crusty - Real-World Protocols
dotSwift 2016 : Beyond Crusty - Real-World ProtocolsdotSwift 2016 : Beyond Crusty - Real-World Protocols
dotSwift 2016 : Beyond Crusty - Real-World Protocols
Rob Napier
 
7 Habits For a More Functional Swift
7 Habits For a More Functional Swift7 Habits For a More Functional Swift
7 Habits For a More Functional Swift
Jason Larsen
 
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kirill Rozov
 
The Ring programming language version 1.5.3 book - Part 34 of 184
The Ring programming language version 1.5.3 book - Part 34 of 184The Ring programming language version 1.5.3 book - Part 34 of 184
The Ring programming language version 1.5.3 book - Part 34 of 184
Mahmoud Samir Fayed
 

Viewers also liked (20)

Intro to Functional Programming in Scala
Intro to Functional Programming in ScalaIntro to Functional Programming in Scala
Intro to Functional Programming in Scala
Shai Yallin
 
Clojure - LISP on the JVM
Clojure - LISP on the JVM Clojure - LISP on the JVM
Clojure - LISP on the JVM
Tikal Knowledge
 
Log Files
Log FilesLog Files
Log Files
Heinrich Hartmann
 
Lambda functions in java 8
Lambda functions in java 8Lambda functions in java 8
Lambda functions in java 8
James Brown
 
Functional Programming in Java
Functional Programming in JavaFunctional Programming in Java
Functional Programming in Java
Narendran Solai Sridharan
 
Functional Programming in Java 8 - Exploiting Lambdas
Functional Programming in Java 8 - Exploiting LambdasFunctional Programming in Java 8 - Exploiting Lambdas
Functional Programming in Java 8 - Exploiting Lambdas
Ganesh Samarthyam
 
2java Oop
2java Oop2java Oop
2java Oop
Adil Jafri
 
2ndQuarter2ndMeeting(formatting number)
2ndQuarter2ndMeeting(formatting number)2ndQuarter2ndMeeting(formatting number)
2ndQuarter2ndMeeting(formatting number)
Esmeraldo Jr Guimbarda
 
Week 5 java script functions
Week 5  java script functionsWeek 5  java script functions
Week 5 java script functions
brianjihoonlee
 
java script functions, classes
java script functions, classesjava script functions, classes
java script functions, classes
Vijay Kalyan
 
TM 2nd qtr-3ndmeeting(java script-functions)
TM 2nd qtr-3ndmeeting(java script-functions)TM 2nd qtr-3ndmeeting(java script-functions)
TM 2nd qtr-3ndmeeting(java script-functions)
Esmeraldo Jr Guimbarda
 
Java Script - Object-Oriented Programming
Java Script - Object-Oriented ProgrammingJava Script - Object-Oriented Programming
Java Script - Object-Oriented Programming
intive
 
02 java programming basic
02  java programming basic02  java programming basic
02 java programming basic
Zeeshan-Shaikh
 
Understanding Java 8 Lambdas and Streams - Part 1 - Lambda Calculus, Lambda...
Understanding Java 8 Lambdas and Streams - Part 1 - Lambda Calculus, Lambda...Understanding Java 8 Lambdas and Streams - Part 1 - Lambda Calculus, Lambda...
Understanding Java 8 Lambdas and Streams - Part 1 - Lambda Calculus, Lambda...
Philip Schwarz
 
Functions in javascript
Functions in javascriptFunctions in javascript
Functions in javascript
baabtra.com - No. 1 supplier of quality freshers
 
JavaScript Functions
JavaScript Functions JavaScript Functions
JavaScript Functions
Reem Alattas
 
Functional programming with Java 8
Functional programming with Java 8Functional programming with Java 8
Functional programming with Java 8
Talha Ocakçı
 
Functional Javascript
Functional JavascriptFunctional Javascript
Functional Javascript
guest4d57e6
 
JavaScript Functions
JavaScript FunctionsJavaScript Functions
JavaScript Functions
Colin DeCarlo
 
Functional programming in java
Functional programming in javaFunctional programming in java
Functional programming in java
John Ferguson Smart Limited
 
Intro to Functional Programming in Scala
Intro to Functional Programming in ScalaIntro to Functional Programming in Scala
Intro to Functional Programming in Scala
Shai Yallin
 
Clojure - LISP on the JVM
Clojure - LISP on the JVM Clojure - LISP on the JVM
Clojure - LISP on the JVM
Tikal Knowledge
 
Lambda functions in java 8
Lambda functions in java 8Lambda functions in java 8
Lambda functions in java 8
James Brown
 
Functional Programming in Java 8 - Exploiting Lambdas
Functional Programming in Java 8 - Exploiting LambdasFunctional Programming in Java 8 - Exploiting Lambdas
Functional Programming in Java 8 - Exploiting Lambdas
Ganesh Samarthyam
 
2ndQuarter2ndMeeting(formatting number)
2ndQuarter2ndMeeting(formatting number)2ndQuarter2ndMeeting(formatting number)
2ndQuarter2ndMeeting(formatting number)
Esmeraldo Jr Guimbarda
 
Week 5 java script functions
Week 5  java script functionsWeek 5  java script functions
Week 5 java script functions
brianjihoonlee
 
java script functions, classes
java script functions, classesjava script functions, classes
java script functions, classes
Vijay Kalyan
 
TM 2nd qtr-3ndmeeting(java script-functions)
TM 2nd qtr-3ndmeeting(java script-functions)TM 2nd qtr-3ndmeeting(java script-functions)
TM 2nd qtr-3ndmeeting(java script-functions)
Esmeraldo Jr Guimbarda
 
Java Script - Object-Oriented Programming
Java Script - Object-Oriented ProgrammingJava Script - Object-Oriented Programming
Java Script - Object-Oriented Programming
intive
 
02 java programming basic
02  java programming basic02  java programming basic
02 java programming basic
Zeeshan-Shaikh
 
Understanding Java 8 Lambdas and Streams - Part 1 - Lambda Calculus, Lambda...
Understanding Java 8 Lambdas and Streams - Part 1 - Lambda Calculus, Lambda...Understanding Java 8 Lambdas and Streams - Part 1 - Lambda Calculus, Lambda...
Understanding Java 8 Lambdas and Streams - Part 1 - Lambda Calculus, Lambda...
Philip Schwarz
 
JavaScript Functions
JavaScript Functions JavaScript Functions
JavaScript Functions
Reem Alattas
 
Functional programming with Java 8
Functional programming with Java 8Functional programming with Java 8
Functional programming with Java 8
Talha Ocakçı
 
Functional Javascript
Functional JavascriptFunctional Javascript
Functional Javascript
guest4d57e6
 
JavaScript Functions
JavaScript FunctionsJavaScript Functions
JavaScript Functions
Colin DeCarlo
 
Ad

Similar to Fp java8 (20)

Gdg almaty. Функциональное программирование в Java 8
Gdg almaty. Функциональное программирование в Java 8Gdg almaty. Функциональное программирование в Java 8
Gdg almaty. Функциональное программирование в Java 8
Madina Kamzina
 
Java8
Java8Java8
Java8
Sunil Kumar
 
Functional aspects of java 8
Functional aspects of java 8Functional aspects of java 8
Functional aspects of java 8
Jobaer Chowdhury
 
Java 8 Workshop
Java 8 WorkshopJava 8 Workshop
Java 8 Workshop
Mario Fusco
 
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
Sharon Rozinsky
 
Functional Programming
Functional ProgrammingFunctional Programming
Functional Programming
Olexandra Dmytrenko
 
TDC2016SP - Código funcional em Java: superando o hype
TDC2016SP - Código funcional em Java: superando o hypeTDC2016SP - Código funcional em Java: superando o hype
TDC2016SP - Código funcional em Java: superando o hype
tdc-globalcode
 
Practical cats
Practical catsPractical cats
Practical cats
Raymond Tay
 
What is new in Java 8
What is new in Java 8What is new in Java 8
What is new in Java 8
Sandeep Kr. Singh
 
Functional programming from its fundamentals
Functional programming from its fundamentalsFunctional programming from its fundamentals
Functional programming from its fundamentals
Mauro Palsgraaf
 
Java 8: more readable and flexible code
Java 8: more readable and flexible codeJava 8: more readable and flexible code
Java 8: more readable and flexible code
WeAreEsynergy
 
Mixing functional programming approaches in an object oriented language
Mixing functional programming approaches in an object oriented languageMixing functional programming approaches in an object oriented language
Mixing functional programming approaches in an object oriented language
Mark Needham
 
Functions in advanced programming
Functions in advanced programmingFunctions in advanced programming
Functions in advanced programming
VisnuDharsini
 
The Ring programming language version 1.2 book - Part 16 of 84
The Ring programming language version 1.2 book - Part 16 of 84The Ring programming language version 1.2 book - Part 16 of 84
The Ring programming language version 1.2 book - Part 16 of 84
Mahmoud Samir Fayed
 
New Functional Features of Java 8
New Functional Features of Java 8New Functional Features of Java 8
New Functional Features of Java 8
franciscoortin
 
Collection implementation classes - Arraylist, linkedlist, Stack
Collection implementation classes - Arraylist, linkedlist, StackCollection implementation classes - Arraylist, linkedlist, Stack
Collection implementation classes - Arraylist, linkedlist, Stack
RajalakshmiS74
 
Mario Fusco - Lazy Java - Codemotion Milan 2018
Mario Fusco - Lazy Java - Codemotion Milan 2018Mario Fusco - Lazy Java - Codemotion Milan 2018
Mario Fusco - Lazy Java - Codemotion Milan 2018
Codemotion
 
Lazy Java
Lazy JavaLazy Java
Lazy Java
J On The Beach
 
Lazy Java
Lazy JavaLazy Java
Lazy Java
Nicola Pedot
 
Lazy java
Lazy javaLazy java
Lazy java
Mario Fusco
 
Gdg almaty. Функциональное программирование в Java 8
Gdg almaty. Функциональное программирование в Java 8Gdg almaty. Функциональное программирование в Java 8
Gdg almaty. Функциональное программирование в Java 8
Madina Kamzina
 
Functional aspects of java 8
Functional aspects of java 8Functional aspects of java 8
Functional aspects of java 8
Jobaer Chowdhury
 
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
Sharon Rozinsky
 
TDC2016SP - Código funcional em Java: superando o hype
TDC2016SP - Código funcional em Java: superando o hypeTDC2016SP - Código funcional em Java: superando o hype
TDC2016SP - Código funcional em Java: superando o hype
tdc-globalcode
 
Functional programming from its fundamentals
Functional programming from its fundamentalsFunctional programming from its fundamentals
Functional programming from its fundamentals
Mauro Palsgraaf
 
Java 8: more readable and flexible code
Java 8: more readable and flexible codeJava 8: more readable and flexible code
Java 8: more readable and flexible code
WeAreEsynergy
 
Mixing functional programming approaches in an object oriented language
Mixing functional programming approaches in an object oriented languageMixing functional programming approaches in an object oriented language
Mixing functional programming approaches in an object oriented language
Mark Needham
 
Functions in advanced programming
Functions in advanced programmingFunctions in advanced programming
Functions in advanced programming
VisnuDharsini
 
The Ring programming language version 1.2 book - Part 16 of 84
The Ring programming language version 1.2 book - Part 16 of 84The Ring programming language version 1.2 book - Part 16 of 84
The Ring programming language version 1.2 book - Part 16 of 84
Mahmoud Samir Fayed
 
New Functional Features of Java 8
New Functional Features of Java 8New Functional Features of Java 8
New Functional Features of Java 8
franciscoortin
 
Collection implementation classes - Arraylist, linkedlist, Stack
Collection implementation classes - Arraylist, linkedlist, StackCollection implementation classes - Arraylist, linkedlist, Stack
Collection implementation classes - Arraylist, linkedlist, Stack
RajalakshmiS74
 
Mario Fusco - Lazy Java - Codemotion Milan 2018
Mario Fusco - Lazy Java - Codemotion Milan 2018Mario Fusco - Lazy Java - Codemotion Milan 2018
Mario Fusco - Lazy Java - Codemotion Milan 2018
Codemotion
 
Ad

Fp java8

  • 1. 1 Ready for "Functional Programming" with Java 8 ? Yanai Franchi , Tikal
  • 2. 2 Agenda ● First-Class Functions ● FP with Streams ● Working Concurrency ● Demo
  • 4. 4 Our Inventory = List of Apples
  • 5. 5 Class Apple ● getColor() : String ● getWeight() : int
  • 8. 8 Filter Green Apples public static List<Apple> filterGreenApples(List<Apple> inventory){ List<Apple> result = new ArrayList<>(); for (Apple apple: inventory){ if (apple.getColor().equals(“green”)) { result.add(apple); } } return result; } Starts empty, add green apples one by one Select only green apples
  • 9. 9 Now Heavy Ones , Please...
  • 10. 10 Easy...We Copy&Paste :( public static List<Apple> filterHeavyApples(List<Apple> inventory){ List<Apple> result = new ArrayList<>(); for (Apple apple: inventory){ if (apple.getWeight() > 150) { result.add(apple); } } return result; } We only change the predicate
  • 11. 11 What's the Difference ? public static List<Apple> filterGreenApples (List<Apple> inventory){ List<Apple> result = new ArrayList<>(); for (Apple apple: inventory){ if (apple.getColor.equals(“green”)) { result.add(apple); } } return result; } public static List<Apple> filterHeavyApples (List<Apple> inventory){ List<Apple> result = new ArrayList<>(); for (Apple apple: inventory){ if (apple.getWeight() > 150) { result.add(apple); } } return result; }
  • 12. 12
  • 13. 13 New Behavior Behavior Parameterization Output apple.getWeight > 150 apple.getColor.equals(“green”) Heavy Apples Green Apples static List<Apple> filterApples( List<Apple> inventory, Predicate<Apple> p) { List<Apple> result = new ArrayList<>(); for (Apple apple: inventory){ if (p.test(apple)) { result.add(apple); } } return result; }
  • 14. 14 In Practice, Our Client...Yuck :( List<Apple> greenApples = filterApples(inventory,new Predicate<Apple>() { @Override public boolean test(Apple a) { return a.getColor().equals(“green”); } }); A lot of “noise”
  • 15. 15
  • 16. 16 Java8 Lambda to Rescue filterApples(inventory, (Apple a) → {return a.getColor().equals(“green”)});
  • 17. 17 Sending Lambda Expression filterApples(inventory, (Apple a) → a.getColor().equals(“green”));
  • 18. 18 Making it Shorter filterApples(inventory, (a) → a.getColor().equals(“green”)); Apple Type is Inferred
  • 19. 19 ...Even Shorter filterApples(inventory, a → a.getColor().equals(“green”));
  • 20. 20 “Capture” Values (a.k.a “Closure”) String color = “green”; filterApples(inventory, a → a.getColor().equals(color)); Implicitly final
  • 21. 21
  • 22. 22 Anonymous Function that Can Be Passed Around filterApples(inventory, a → a.equals.getColor(“green”));
  • 23. 23 Switch to Method Reference filterApples(inventory,a → a.equals.getColor(“green”));
  • 24. 24 Switch to Method Reference filterApples(inventory,Apple::isGreen); filterApples(inventory,a → a.getColor().equals(“green”)); isGreen is declared in Apple
  • 27. 27 Lambda Type = Functional Interface Predicate<Apple> redApple = a → a.getColor().equals(“red”); Predicate is the type of our lambda
  • 28. 28 Meet Functional Interface @FunctionalInterface public interface Predicate<T>{ boolean test(T t); } Just Marker ● Definition: a functional interface is an interface with one abstract method ● Single Abstract Method (SAM) type SAM
  • 29. 29 Default Methods Implementations in Interface @FunctionalInterface public interface Predicate<T>{ boolean test(T t); default Predicate<T> negate(){ return (t) -> !test(t); } default or(Predicate<? super T> other){ return (t) -> test(t) || other.test(t); } default and(Predicate<? super T> other){ return (t) -> test(t) && other.test(t); } } Default Method
  • 30. 30 Existing Function Interfaces interface Comparator<T> { boolean compare(T x, T y); } (int x, int y) → x - y ; interface FileFilter { boolean accept(File x); } f → f.isDirectory() interface Runnable { void run(); } () → someCode(); interface ActionListener{ void actionPerformed(ActionEvent ae); } (ae -> log.debug(“Got it!”));
  • 31. 31 New Function Interfaces ● Predicate<T> : boolean test(T t); – Determine if the input of type T matches some criteria : ● Consumer<T> : void accept(T t); – Accept a single input argument of type T, and return no result : ● Supplier<T> : T get(); – A factory that’s expected to return either a new instance or a pre-created instance : ● Function<T, R> : R apply(T t); – Apply a function to the input type T, generating a result of type R
  • 32. 32
  • 33. 33 Sorting with Anonymous Class inventory.sort(new Comparator<Apple>() { public int compare(Apple a1, Apple a2){ return a1.getWeight().compareTo(a2.getWeight()); } }); High Order Function
  • 34. 34 Sort with Lambda inventory.sort( (a1,a2) → a1.getWeight().compareTo(a2.getWeight()) );
  • 35. 35 Using “comparing” Method Comparator Interface Static method inventory.sort(comparing(Apple::getWeight)); Static method that accept Function and return Comparator
  • 37. 37 Dish Row 1 Row 2 Row 3 Row 4 0 2 4 6 8 10 12 Column 1 Column 2 Column 3 ● String getName() ● boolean isVegeterian() ● int getCalories() ● Type getType() ● List<String> getNickNames() ● CaloricLevel getCaloricLevel()
  • 38. 38 Three Fat Dishes - Imperative ● Client controls iteration ● Inherently serial: iterate from beginning to end ● Not thread-safe because business logic is stateful (mutable accumulator variable) ● Frustratingly imperative List<String> fatsDishes = ... int count = 0; for(Dish d : menu){ if (count > 3) break; if(d.getCalories > 300){ count++; fatsDishes.add(d.getName()); } } External Iteration
  • 39. 39
  • 40. 40 FP → Declarative Code List<String> fatDishes = menu.stream() .filter(d -> d.getCalories() > 300) .map(Dish::getName) .limit(3) .collect(toList());
  • 41. 41
  • 42. 42 But What is a Stream ? ● A sequence of elements from a source that supports aggregate operations – Aimed for computations and aggregations (In contrary to collections which are data structures) – Consume from a data-providing source such as Collections, Arrays, or IO resources. – Support SQL-like operations and common operations from functional programing languages such as filter, map, reduce, find, match, sorted etc.
  • 43. 43 Creating Stream ● IntStream.range(1, 100) ● Stream.of("Java 8 ", "Lambdas"); ● File.list(Paths.get("some-folder")) ● Files.lines(Paths.get("data.txt")) ● myList.parallelStream() ● Create infinite stream – Iterate ● Stream.iterate(0, n -> n + 2) ● Stream.iterate(new int[]{0, 1}, t -> new int[]{t[1], t[0]+t[1]}) – Stream.generate(Math::random)
  • 44. 44 High Order Function - map ● <R> Stream<R> map(Function<? super T, ? extends R> mapper); ● Apply the mapper function on each element of the stream , and create a new stream from its outputs by placing the results of the mapper on the new stream ● map(Dish::getName). Converts a Stream of dishes to Stream names (Strings), by applying Dish.getName() on the elements.
  • 45. 45 High Order Function - flatMap ● <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper); ● Apply the mapper function on each element of the stream and create a new stream from its outputs, by placing contents of the mapped streams in the new stream ● menu.stream().flatMap(d → d.getNickNames().stream()) – Converts a Stream of dishes to Stream of nickNames (String), by replacing all nicknames as elements of the stream.
  • 46. 46 Limit - “Short Circuit” List<String> names = menu.stream() .filter(d -> {System.out.println("filtering" + d); return d.getCalories() > 300;}) .map(d -> {System.out.println("mapping" + d); return d.getName();}) .limit(3) .collect(toList()); filtering pork mapping pork filtering beef filtering chicken mapping chicken filtering egg filtering spaghetti mapping spaghetti Short Circuit: Stopped printing after 3 dishes
  • 47. 47 Finding & Matching - “Short Circuit” ● No need to process the whole stream ● As soon as an element is found a result can be produced. ● Finding Operations: – anyMatch, noneMatch, findFirst and findAny boolean found = menu.stream().anyMatch(Dish::isVegatarian)
  • 48. 48 Group Dishes by Type - Imperative Map<Dish.Type, List<Dish>> groupDishesByTypeMap = new HashMap<>(); for (Dish dish : menu) { final Type type = dish.getType(); List<Dish> dishesForType = groupDishesByTypeMap.get(type); if(dishesForType == null){ dishesForType = new ArrayList<>(); groupDishesByTypeMap.put(type, dishesForType); } dishesForType.add(dish); } return groupDishesByTypeMap;
  • 49. 49 Grouping with FP - Declarative Map<Dish.Type, List<Dish>> groupDishesByTypeMap = menu.stream().collect(groupingBy(Dish::getType)); Collectors static method
  • 50. 50 Count Dishes Per Type Map<Dish.Type, Long> typesCount = menu.stream().collect( groupingBy(Dish::getType,counting())); {MEAT=3, FISH=2, OTHER=4} Output Collectors static method
  • 52. 52 One More Level... Map<Dish.Type, Map<CaloricLevel, List<Dish>>> groupDishesByTypeAndCaloricLevel = menu.stream() .collect(groupingBy( Dish::getType, groupingBy(Dish::getCaloricLevel))); { MEAT={DIET=[chicken], NORMAL=[beef], FAT=[pork]}, FISH={DIET=[prawns], NORMAL=[salmon]}, OTHER={DIET=[rice, seasonal fruit], NORMAL=[french fries, pizza]} } Output
  • 54. 54 Process Dishes in Parallel ● Uses the ForkJoin framework behind the scenes ● By Default number of threads is as the number of processors ● Will NOT keep the original order of the stream menu.parallelStream().forEach(Dish::heavyCalculation);
  • 55. 55 Total Calories in Menu – Imperative int i=0; for (Dish dish : menu) { i += dish.getCalories(); } Side Effect
  • 56. 56 We Know What To Do... ● The only difference is the reduction function ● For min, max, avg etc – The code will look the same int i=0; for (Dish dish : menu) { i += dish.getCalories(); } int i=0; for (Dish dish : menu) { i = Math.max(dish.getCalories(),i); }
  • 57. 57 Move To FP – Bad Way :( Accumulator accumulator = new Accumulator(); menu.stream() .map(Dish::getCalories) .forEach(accumulator::add); accumulator.getTotal(); class Accumulator { private long total = 0; long getTotal(){return total); public void add(long value) { total += value; } } Side Effect
  • 58. 58 Break Concurrency!!! :( Accumulator accumulator = new Accumulator(); menu.parallelStream() .map(Dish::getCalories) .forEach(accumulator::add) accumulator.getTotal(); Different result For the same input
  • 59. 59 Reducing Row 1 Row 2 Row 3 Row 4 0 2 4 6 8 10 12 Column 1 Column 2 Column 3 menu.parallelStream() .map(Dish::getCalories) .sum(); menu.parallelStream() .map(Dish::getCalories) .reduce(0,Integer:sum); =
  • 60. 60 FP - Data is Immutable ● Once object is created, it can't be changed. ● If you need to change an object, make a copy. – Enables concurrency – Rollback of data – Simplicity
  • 61. 61 Mutable Tree – What's Wrong ? class Tree { private String key; private int val; private Tree left, right; public Tree(String k, int v, Tree l, Tree r) { key = k; val = v; left = l; right = r; } } public static Tree update(String k, int newval, Tree t) { if (t == null) t = new Tree(k, newval, null, null); else if (k.equals(t.key)) t.val = newval; else if (k.compareTo(t.key) < 0) t.left = update(k, newval, t.left); else t.right = update(k, newval, t.right); return t; }
  • 62. 62 Concurrency Problems ● Every user wants to share the identical data structure and see updates caused by any part of the program. ● Hence it is vital (but often overlooked) in nonfunctional code that whenever we add some form of structured value to a tree then we copy it - Who knows, someone may later assume they can update it. ● In Functional approach – Share storage for common parts of structure.
  • 66. 66 Persistent Tree class Tree { private String key; private int val; private Tree left, right; public Tree(String k, int v, Tree l, Tree r) { key = k; val = v; left = l; right = r; } } public static Tree fupdate(String k, int newval, Tree t) { return (t == null) ? new Tree(k, newval, null, null) : k.equals(t.key) ? new Tree(k, newval, t.left, t.right) : k.compareTo(t.key) < 0 ? new Tree(t.key, t.val, fupdate(k,newval, t.left), t.right) : new Tree(t.key, t.val, t.left, fupdate(k,newval, t.right)); }
  • 68. 68 Analyze Multiple Apache Logs ● Host, Time, Request, Response, Resp-Length 199.72.81.55 - - [02/Jul/1995:00:00:01 -0400] "GET /history/apollo/ HTTP/1.0" 200 6245 unicomp6.unicomp.net - - [02/Jul/1995:00:00:06 -0400] "GET /shuttle/countdown/ HTTP/1.0" 200 3985 199.120.110.21 - - [01/Jul/1995:00:00:09 -0400] "GET /shuttle/missions/sts-73/mission-sts-73.html HTTP/1.0" 200 4085 burger.letters.com - - [01/Jul/1995:00:00:11 -0400] "GET /shuttle/countdown/liftoff.html HTTP/1.0" 304 0 199.120.110.21 - - [01/Jul/1995:00:00:11 -0400] "GET /shuttle/missions/sts-73/sts-73-patch-small.gif HTTP/1.0" 200 4179 burger.letters.com - - [01/Jul/1995:00:00:12 -0400] "GET /images/NASA-logosmall.gif HTTP/1.0" 304 0 burger.letters.com - - [01/Jul/1995:00:00:12 -0400] "GET /shuttle/countdown/video/livevideo.gif HTTP/1.0" 200 0 205.212.115.106 - - [01/Jul/1995:00:00:12 -0400] "GET /shuttle/countdown/countdown.html HTTP/1.0" 200 3985 d104.aa.net - - [01/Jul/1995:00:00:13 -0400] "GET /shuttle/countdown/ HTTP/1.0" 200 3985 129.94.144.152 - - [01/Jul/1995:00:00:13 -0400] "GET / HTTP/1.0" 200 7074 unicomp6.unicomp.net - - [01/Jul/1995:00:00:14 -0400] "GET /shuttle/countdown/count.gif HTTP/1.0" 200 40310 unicomp6.unicomp.net - - [01/Jul/1995:00:00:14 -0400] "GET /images/NASA-logosmall.gif HTTP/1.0" 200 786 unicomp6.unicomp.net - - [01/Jul/1995:00:00:14 -0400] "GET /images/KSC-logosmall.gif HTTP/1.0" 200 1204 d104.aa.net - - [01/Jul/1995:00:00:15 -0400] "GET /shuttle/countdown/count.gif HTTP/1.0" 200 40310 d104.aa.net - - [01/Jul/1995:00:00:15 -0400] "GET /images/NASA-logosmall.gif HTTP/1.0" 200 786 d104.aa.net - - [01/Jul/1995:00:00:15 -0400] "GET /images/KSC-logosmall.gif HTTP/1.0" 200 1204 129.94.144.152 - - [01/Jul/1995:00:00:17 -0400] "GET /images/ksclogo-medium.gif HTTP/1.0" 304 0 199.120.110.21 - - [01/Jul/1995:00:00:17 -0400] "GET /images/launch-logo.gif HTTP/1.0" 200 1713 ppptky391.asahi-net.or.jp - - [01/Jul/1995:00:00:18 -0400] "GET /facts/about_ksc.html HTTP/1.0" 200 3977 ppptky391.asahi-net.or.jp - - [01/Jul/1995:00:00:19 -0400] "GET /images/launchpalms-small.gif HTTP/1.0" 200 11473 205.189.154.54 - - [01/Jul/1995:00:00:24 -0400] "GET /shuttle/countdown/ HTTP/1.0" 200 3985 … ... 199.72.81.55 - - [02/Jul/1995:00:00:01 -0400] "GET /history/apollo/ HTTP/1.0" 200 6245 unicomp6.unicomp.net - - [02/Jul/1995:00:00:06 -0400] "GET /shuttle/countdown/ HTTP/1.0" 200 3985 199.120.110.21 - - [01/Jul/1995:00:00:09 -0400] "GET /shuttle/missions/sts-73/mission-sts-73.html HTTP/1.0" 200 4085 burger.letters.com - - [01/Jul/1995:00:00:11 -0400] "GET /shuttle/countdown/liftoff.html HTTP/1.0" 304 0 199.120.110.21 - - [01/Jul/1995:00:00:11 -0400] "GET /shuttle/missions/sts-73/sts-73-patch-small.gif HTTP/1.0" 200 4179 burger.letters.com - - [01/Jul/1995:00:00:12 -0400] "GET /images/NASA-logosmall.gif HTTP/1.0" 304 0 burger.letters.com - - [01/Jul/1995:00:00:12 -0400] "GET /shuttle/countdown/video/livevideo.gif HTTP/1.0" 200 0 205.212.115.106 - - [01/Jul/1995:00:00:12 -0400] "GET /shuttle/countdown/countdown.html HTTP/1.0" 200 3985 d104.aa.net - - [01/Jul/1995:00:00:13 -0400] "GET /shuttle/countdown/ HTTP/1.0" 200 3985 129.94.144.152 - - [01/Jul/1995:00:00:13 -0400] "GET / HTTP/1.0" 200 7074 unicomp6.unicomp.net - - [01/Jul/1995:00:00:14 -0400] "GET /shuttle/countdown/count.gif HTTP/1.0" 200 40310 unicomp6.unicomp.net - - [01/Jul/1995:00:00:14 -0400] "GET /images/NASA-logosmall.gif HTTP/1.0" 200 786 unicomp6.unicomp.net - - [01/Jul/1995:00:00:14 -0400] "GET /images/KSC-logosmall.gif HTTP/1.0" 200 1204 d104.aa.net - - [01/Jul/1995:00:00:15 -0400] "GET /shuttle/countdown/count.gif HTTP/1.0" 200 40310 d104.aa.net - - [01/Jul/1995:00:00:15 -0400] "GET /images/NASA-logosmall.gif HTTP/1.0" 200 786 d104.aa.net - - [01/Jul/1995:00:00:15 -0400] "GET /images/KSC-logosmall.gif HTTP/1.0" 200 1204 129.94.144.152 - - [01/Jul/1995:00:00:17 -0400] "GET /images/ksclogo-medium.gif HTTP/1.0" 304 0 199.120.110.21 - - [01/Jul/1995:00:00:17 -0400] "GET /images/launch-logo.gif HTTP/1.0" 200 1713 ppptky391.asahi-net.or.jp - - [01/Jul/1995:00:00:18 -0400] "GET /facts/about_ksc.html HTTP/1.0" 200 3977 ppptky391.asahi-net.or.jp - - [01/Jul/1995:00:00:19 -0400] "GET /images/launchpalms-small.gif HTTP/1.0" 200 11473 205.189.154.54 - - [01/Jul/1995:00:00:24 -0400] "GET /shuttle/countdown/ HTTP/1.0" 200 3985 … ... 199.72.81.55 - - [02/Jul/1995:00:00:01 -0400] "GET /history/apollo/ HTTP/1.0" 200 6245 unicomp6.unicomp.net - - [02/Jul/1995:00:00:06 -0400] "GET /shuttle/countdown/ HTTP/1.0" 200 3985 199.120.110.21 - - [01/Jul/1995:00:00:09 -0400] "GET /shuttle/missions/sts-73/mission-sts-73.html HTTP/1.0" 200 4085 burger.letters.com - - [01/Jul/1995:00:00:11 -0400] "GET /shuttle/countdown/liftoff.html HTTP/1.0" 304 0 199.120.110.21 - - [01/Jul/1995:00:00:11 -0400] "GET /shuttle/missions/sts-73/sts-73-patch-small.gif HTTP/1.0" 200 4179 burger.letters.com - - [01/Jul/1995:00:00:12 -0400] "GET /images/NASA-logosmall.gif HTTP/1.0" 304 0 burger.letters.com - - [01/Jul/1995:00:00:12 -0400] "GET /shuttle/countdown/video/livevideo.gif HTTP/1.0" 200 0 205.212.115.106 - - [01/Jul/1995:00:00:12 -0400] "GET /shuttle/countdown/countdown.html HTTP/1.0" 200 3985 d104.aa.net - - [01/Jul/1995:00:00:13 -0400] "GET /shuttle/countdown/ HTTP/1.0" 200 3985 129.94.144.152 - - [01/Jul/1995:00:00:13 -0400] "GET / HTTP/1.0" 200 7074 unicomp6.unicomp.net - - [01/Jul/1995:00:00:14 -0400] "GET /shuttle/countdown/count.gif HTTP/1.0" 200 40310 unicomp6.unicomp.net - - [01/Jul/1995:00:00:14 -0400] "GET /images/NASA-logosmall.gif HTTP/1.0" 200 786 unicomp6.unicomp.net - - [01/Jul/1995:00:00:14 -0400] "GET /images/KSC-logosmall.gif HTTP/1.0" 200 1204 d104.aa.net - - [01/Jul/1995:00:00:15 -0400] "GET /shuttle/countdown/count.gif HTTP/1.0" 200 40310 d104.aa.net - - [01/Jul/1995:00:00:15 -0400] "GET /images/NASA-logosmall.gif HTTP/1.0" 200 786 d104.aa.net - - [01/Jul/1995:00:00:15 -0400] "GET /images/KSC-logosmall.gif HTTP/1.0" 200 1204 129.94.144.152 - - [01/Jul/1995:00:00:17 -0400] "GET /images/ksclogo-medium.gif HTTP/1.0" 304 0 199.120.110.21 - - [01/Jul/1995:00:00:17 -0400] "GET /images/launch-logo.gif HTTP/1.0" 200 1713 ppptky391.asahi-net.or.jp - - [01/Jul/1995:00:00:18 -0400] "GET /facts/about_ksc.html HTTP/1.0" 200 3977 ppptky391.asahi-net.or.jp - - [01/Jul/1995:00:00:19 -0400] "GET /images/launchpalms-small.gif HTTP/1.0" 200 11473 205.189.154.54 - - [01/Jul/1995:00:00:24 -0400] "GET /shuttle/countdown/ HTTP/1.0" 200 3985 … ...
  • 69. 69 Requirements ● Answer the following: – Are there any errors ? – Are there any empty-body responses ? – Find last 5 error – Count statuses for each day ● Assumptions – Analyze multiple logs in “logs” folder – Logs files are big and can't fit into memory
  • 70. 70 Design ● LogEntry - Entity Class – parse(String line) : LogEntry ● LogAnalyticService – Service Class – streamLogs() : Stream<LogEntry> ● Stream log files in folder ● Per Each file Stream lines ● Map each line to LogEntry ● anyMatch – Reuse for different predicates ● groupBy – For grouping
  • 71. 71 Implementation private Stream<LogEntry> streamLogs() { try { return Files.list(Paths.get(loggingDir)) .filter(p -> p.getFileName().endsWith(LOG_EXT)) .flatMap(Files::lines) .map(LogEntry::parse); } catch (final Exception e) { throw new RuntimeException(e); } } Will not Compile
  • 72. 72 private Stream<LogEntry> streamLogs() { try { return Files.list(Paths.get(loggingDir)) .filter(p -> p.getFileName().endsWith(LOG_EXT)) .flatMap(this::lines) .map(LogEntry::parse); } catch (final Exception e) { throw new RuntimeException(e); } } private Stream<String> lines(final Path path) { try { return Files.lines(path); } catch (IOException e) { logger.error("Failed to process "+path,e); return Stream.empty(); } }
  • 73. 73 Last Err Logs return streamLogs() .filter((le) -> le.getResponse() >= 500) .sorted(comparing(LogEntry::getDateTime).reversed()) .limit(5) .collect(toList());
  • 74. 74 Sending Predicates public boolean isAnyWithResponse(int response) { return anyMatch((le) -> le.getResponse() == response); } public boolean isAnyEmptyResponse() { return anyMatch((le) -> le.getByteSent() == 0); } boolean anyMatch(Predicate<? super LogEntry> predicate) { return streamLogs().anyMatch(predicate); }
  • 75. 75 Grouping Results Map<LocalDate, Map<Integer, Long>> groupingByDatesThenResponse() { return streamLogs() .collect(groupingBy( LogEntry::getDate, TreeMap::new, groupingBy(LogEntry::getResponse, counting())) ); } Ordered Keys Nested Grouping
  • 77. 77 FP Summary ● Functions are first-class citizens – Can be declared as variables, pass as arguments or be returned by other functions ● Declarative instead of imperative – We tell what to do, instead of how ● Data Immutability – Reduce Side Effect – Easier path to parallel code ● Java 8 Lambda & Streams enable FP style