SlideShare a Scribd company logo
1 of 80
Download to read offline
Ten common mistakes
made with Function Java
Brian Vermeer (@BrianVerm)
Brian Vermeer
Software Engineer
Doing too much in a single lambda
Lambda Expression
In computer programming, a lambda expression is a function definition
that is not bound to an identifier. Anonymous functions are often:[1]
• arguments being passed to higher-order functions, or
• used for constructing the result of a higher-order function that
needs to return a function.
Lambda in Java
Anonymous Inner functions
Satisfy a Functional Interface
They only exist in runtime
Single Line <input> -> <output> or Block <input> -> { function body }
Example
public void execute() {
Beer grolsch = new Beer("Grolsche", 4.3);
String result = handleBeer(grolsch,
beer -> grolsch.getName() + "-" + grolsch.getAlcohol());
System.out.println(result);
}
private String handleBeer(Beer beer, Function<Beer, String> func) {
System.out.println("handling beer " + beer.getName());
return func.apply(beer);
}
//Output : Grolsche-4.3
Don’t do Block Lambda
beer -> {
String name;
if (beer.getName().contains(" ")) {
name = beer.getName().replace(" ", "");
} else {
name = beer.getName();
}
try {
name += Integer.parseInt(beer.getAlcoholPrecentage().toString());
} catch (NumberFormatException nfe) {
name += beer.getAlcoholPrecentage();
}
return name;
}
Transform to a methode
private String createFullName (Beer beer){
String name;
if (beer.getName().contains(" ")) {
name = beer.getName().replace(" ", "");
} else {
name = beer.getName();
}
try {
name += Integer.parseInt(beer.getAlcoholPrecentage().toString());
} catch (NumberFormatException nfe) {
name += beer.getAlcoholPrecentage();
}
return name;
}
handleBeer(grolsch, this::createFullName);
Returning a Stream
A stream is NOT a
data structure
A stream is NOT a
data structure
A stream is NOT a
data structure
What is Stream ( in Java)
Flow of data derived from a Collection
Can create a pipeline of function that can be evaluated
Intermediate result
Lazy evaluated by nature
Can transform data, cannot mutate data
JAVA Streams
stringLists.stream()

.map(str -> str.toUpperCase())

.collect(Collectors.toList());
Intermediate
filter 

distinct

map 

flatMap

Terminal
reduce

collect

toArray

count

max

min

limit 

skip

sorted

peek
findAny

findFirst

forEach

allMatch

anyMatch
List<Beer> beers = getBeers();

Stream<Beer> beerStream = beers.stream();



beerStream.forEach(b ->System.out.println(b.getName())); //1


beerStream.forEach(b ->System.out.println(b.getAlcohol())); //2
Only use a Stream once
Line 2 will give: 



java.lang.IllegalStateException: stream has already been operated upon or
closed
public Stream<Beer> getMeMyBeers()
public void execute() {
getMeMyBeers() //don’t know if it is consumed yet!!!!
…
}
Don’t return a Stream
Not Consuming a Stream
List<Beer> beers = List.of(new Beer("Heineken", 5.2), new Beer("Delirium
Tremens", 9.0), new Beer("Amstel", 5.1));
beers.stream()

.limit(10)

.map(i -> i.getAlcohol())

.peek(i -> {

if (i > 7.0)

throw new RuntimeException();

});
Consume the stream
List<Beer> beers = List.of(new Beer("Heineken", 5.2), new Beer("Delirium
Tremens", 9.0), new Beer("Amstel", 5.1));
beers.stream()

.limit(10)

.map(i -> i.getAlcohol())

.peek(i -> {

if (i > 7.0)

throw new RuntimeException();

})
.forEach(System.out::println);
Consume the stream
5.2
Exception in thread "main" java.lang.RuntimeException
Mutable Object
Functional Programming
In computer science, functional programming is a programming
paradigma style of building the structure and elements of computer
programs that treats computation as the evaluation of mathematical
functions and avoids changing-state and mutable data.
It is a declarative programming paradigm, which means programming is
done with expressions or declarations instead of statements.
— wikipedia
– Kevlin Henney
“Asking a question should not
change the answer, nor
should asking it twice”
Immutable objects
Less moving parts
Easier to reason about code
No need to keep a mental map of the state an object is in.
Stream cannot mutate
private final List<Beer> beers = List.of(new Beer("Heineken", 5.2),
new Beer("Amstel", 5.1));
public void execute() {
List<Beer> beersNew = beers.stream()
.map(beer -> beer.setName(“foo”)) //not allowed
.collect(Collectors.toList());
}
Stream should not mutate !
private class Beer {
String name;
Double alcohol;
public Beer setName(String name){
this.name = name;
return this;
}
}
private final List<Beer> beers = List.of(new Beer("Heineken", 5.2), new Beer("Amstel",
5.1));
public void execute() {
List<Beer> beersNew = beers.stream()
.map(beer -> beer.setName("foo"))
.collect(Collectors.toList());
System.out.println(beers);
System.out.println(beersNew);
}
Stream should not mutate !
private class Beer {
String name;
Double alcohol;
public Beer setName(String name){
this.name = name;
return this;
}
}
private final List<Beer> beers = List.of(new Beer("Heineken", 5.2), new Beer("Amstel",
5.1));
public void execute() {
List<Beer> beersNew = beers.stream()
.map(beer -> beer.setName("foo"))
.collect(Collectors.toList());
System.out.println(beers);
System.out.println(beersNew);
}
Return a new copy
private class Beer {
String name;
Double alcohol;
public Beer withName(String name){
return new Beer(name, this.alcohol);
}
}
private final List<Beer> beers = List.of(new Beer("Heineken", 5.2), new Beer("Amstel",
5.1));
public void execute() {
List<Beer> beersNew = beers.stream()
.map(beer -> beer.withName("foo"))
.collect(Collectors.toList());
System.out.println(beers);
System.out.println(beersNew);
}
Overusing forEach
forEach()
Terminal functional on a stream.
Takes a consumer.
Can be used to apply side effects.
for-loop without the external iterator
simple forEach example
List<String> names = List.of("James", "Trisha", "Joshua",
"Jessica","Simon", “Heather");
names.stream()
.map(String::toUpperCase)
.forEach(System.out::println);
mutation with forEach
List<Beer> beers = List.of(new Beer("Heineken", 5.2), new
Beer("Amstel", 5.1));
beers.stream()
.forEach(beer -> beer.setAlcohol(0.0));
overusing forEach
private class Beer {
String name;
Double alcohol;
List<String> reviews;
Integer rating;
}
List<Beer> beers = List.of(new Beer("Heineken", 5.2), new Beer("Amstel", 5.1));
//enrich with ratings
beers.stream().forEach(beer -> beer.setRating(findRating(beer.getName())));
//enrich with reviews
beers.stream().forEach(beer -> beer.setReviews(findReviews(beer.getName())));
…
Order of operations
Assignment
Beers -> Brewer -> Country
I want the first 3 unique brewers countries from the beer library as comma separated String
beerLib.stream()
.map(Beer::getBrewer)
.distinct()
.limit(3)
.map(Brewer::getCountry)
.map(String::toUpperCase)
.collect(Collectors.joining(“,”));
Assignment
Beers -> Brewer -> Country
I want the first 3 unique brewers countries from the beer library as comma separated String
beerLib.stream()
.map(Beer::getBrewer)
.distinct()
.limit(3)
.map(Brewer::getCountry)
.map(String::toUpperCase)
.collect(Collectors.joining(“,”));
// wrong
Assignment
Beers -> Brewer -> Country
I want the first 3 unique brewers countries from the beer library as comma separated String
beerLib.stream()
.map(Beer::getBrewer)
.map(Brewer::getCountry)
.map(String::toUpperCase)
.distinct()
.limit(3)
.collect(Collectors.joining(“,”));
// correct
Infinite stream
IntStream.iterate(0, i -> ( i + 1) % 2)

.distinct()

.limit(10)

.forEach(i -> System.out.println(i));
Infinite stream
IntStream.iterate(0, i -> ( i + 1) % 2)

.distinct()

.limit(10)

.forEach(i -> System.out.println(i));

// will run forever
IntStream.iterate(0, i -> ( i + 1) % 2)

.limit(10)

.distinct()

.forEach(i -> System.out.println(i));
//will terminate
Infinite stream
IntStream.iterate(0, i -> ( i + 1) % 2)

.parallel()
.distinct()

.limit(10)

.forEach(i -> System.out.println(i));

// will run forever on all threads.
Solution
1. Look closely at the order of operations

- prevent incorrect answers



2. Only use infinite streams when absolutely necessary.
rather use: 

IntStream.range(0,10);
IntStream.rangeClosed(0,10);
IntStream.iterate(0, i -> i < 10, i -> i + 1); //java 9 and up
Getting an Optional
Optional
Java’s implementation of the Maybe Monad
Encapsulation to handle possible null value
Consider it a wrapper where a value can be absent
Force the user to unpack the Optional before using it.
Optional
Optional<String> c = null //please avoid this
public void execute() {
Optional<String> maybeString = getText();
String unpacked = maybeString.get();
}
Unpack Optional
public void execute() {
Optional<String> maybeString = getText();
String unpacked = maybeString.get();
}
Unpack Optional
NoSuchElementException
public void execute() {
Optional<String> maybeString = getText();
String unpacked = maybeString.get();
}
Unpack Optional
public void execute() {
Optional<String> maybeString = getText();
if (maybeString.isPresent()) {
String unpacked = maybeString.get();
}
}
NoSuchElementException
Unpack Optional
public void execute() {
Optional<String> maybeString = getText();
maybeString.ifPresent( str -> /* doSomething */ );
}
public void execute() {
Optional<String> maybeString = getText();
maybeString.map(str -> str + “.");
}
What else ..??
Alternative flow
- orElse()
- orElseGet()
- orElseThrow()
orElseThrow
public void execute() {

Optional<String> maybeString = Optional.empty();

maybeString

.map(this::runIfExist)

.orElseThrow(() -> new RuntimeException("Optional was empty"));

}
orElse
public void execute() {

Optional<String> maybeString = Optional.of("foo");

String newString = maybeString

.map(this::runIfExist)

.orElse(runIfEmpty());

System.out.println(newString);

}

private String runIfExist(String str) {

System.out.println("only run if optional is filled ");

return str;

}

private String runIfEmpty() {

System.out.println("only run if empty");

return "empty";

}
orElse
public void execute() {

Optional<String> maybeString = Optional.of("foo");

String newString = maybeString

.map(this::runIfExist)

.orElse(runIfEmpty());

System.out.println(newString);

}

private String runIfExist(String str) {

System.out.println("only run if optional is filled ");

return str;

}

private String runIfEmpty() {

System.out.println("only run if empty");

return "empty";

}
only run if optional is filled
only run if empty
foo
orElseGet
public void execute() {

Optional<String> maybeString = Optional.of("foo");

String newString = maybeString

.map(this::runIfExist)

.orElseGet(() -> runIfEmpty());

System.out.println(newString);

}

private String runIfExist(String str) {

System.out.println("only run if optional is filled ");

return str;

}

private String runIfEmpty() {

System.out.println("only run if empty");

return "empty";

}
orElseGet
public void execute() {

Optional<String> maybeString = Optional.of("foo");

String newString = maybeString

.map(this::runIfExist)

.orElseGet(() -> runIfEmpty());

System.out.println(newString);

}

private String runIfExist(String str) {

System.out.println("only run if optional is filled ");

return str;

}

private String runIfEmpty() {

System.out.println("only run if empty");

return "empty";

}
only run if optional is filled
foo
what else?
- When using orElse(x), make sure x doesn’t contain any side effects
- Only use orElse() to assign a default value
- Use orElseGet() to run an alternative flow
Exceptions
Checked Exceptions & Lambda
public Beer doSomething(Beer beer) throws IsEmptyException { …}
Function <Beer,Beer> fBeer = beer -> doSomething(beer)


Checked Exceptions & Lambda
public Beer doSomething(Beer beer) throws IsEmptyException { …}
Function <Beer,Beer> fBeer = beer -> doSomething(beer)


Checked Exceptions & Lambda
public Beer doSomething(Beer beer) throws IsEmptyException { …}
beerLib.stream()
.map(beer -> {

try{

return doSomething(beer);

} catch (IsEmptyException e) {

throw new RuntimeException(e);

}

};)
.collect(Collectors.toList());
//not very pretty
Checked Exceptions & Lambda
public Beer doSomething(Beer beer) throws IsEmptyException { …}
private Beer wrappedDoSomeThing(Beer beer) {

try{

return doSomething(beer);

} catch (IsEmptyException e) {

throw new RuntimeException(e);

}

}
beerLib.stream()
.map(this::wrappedDoSomeThing)
.collect(Collectors.toList());
Exception Utility
@FunctionalInterface

public interface CheckedFunction<T, R> {

public R apply(T t) throws Throwable;

}
public static <T, R> Function<T, R> wrap(CheckedFunction<T, R> function) {

return t -> {

try {

return function.apply(t);

} catch (Throwable ex) {

throw new RuntimeException(ex);

}

};

};
beerLib.stream()
.map(beer -> wrap(doSomething(beer)))
.collect(Collectors.toList());
Either type
public class Either<L, R> {
private final L left;
private final R right;
private Either(L left, R right) {
this.left = left;
this.right = right;
}
public static <L,R> Either<L,R> Left( L value) {
return new Either(value, null);
}
public static <L,R> Either<L,R> Right( R value) {
return new Either(null, value);
} …
}
Either type
private Either<Exception, String> canGoWrong(Integer input) {
if (input > 10) {
return Either.Left(new RuntimeException("larger then 10"));
}
return Either.Right("["+input+"]");
}
List<Either<Exception, String>> canGoWrongs = IntStream.range(0,12)
.mapToObj(i -> canGoWrong(i))
.collect(Collectors.toList());
Either type
private Either<Exception, String> canGoWrong(Integer input) {
if (input > 10) {
return Either.Left(new RuntimeException("larger then 10"));
}
return Either.Right(“["+input+"]");
}
List<Either<Exception, String>> canGoWrongs = IntStream.range(0,12)
.mapToObj(i -> canGoWrong(i))
.collect(Collectors.toList());
canGoWrongs.stream()
.map(e -> e.mapRight(s -> s.toUpperCase()))
.flatMap(o -> o.map(Stream::of).orElseGet(Stream::empty))
.forEach(System.out::println);
More with streams
//java 9
List myList = List.of(1,2,3,4,5)
//pre Java9
List myList = Arrays.asList(new String[] {“a”,"b","c"});
Creating collections
//java 9
List myList = List.of(1,2,3,4,5)
//pre Java9
List myList = Arrays.asList(new String[] {"a","b","c"});
// since Java 8
List myList = Stream.of("a","b","c","d").collect(Collectors.toList());
Creating collections
private Beer foo(){...}
private Beer bar(){...}
private Beer fooBar(){…}
Beer myBeer = new Beer();
Beer result = fooBar(bar(foo(myBeer)));
Using Stream.of
private Beer foo(){...}
private Beer bar(){...}
private Beer fooBar(){…}
Beer myBeer = new Beer();
Beer result = fooBar(bar(foo(myBeer)));
Using Stream.of
Beer result = Stream.of(myBeer)
.map(this::foo)

.map(this::bar)

.map(this::fooBar)

.findFirst().get();
String sentence = "The quick fox jumps over the lazy dog. ";
String[] words = sentence
.trim()
.toUpperCase()
.split(" ");
for(String word : words) {
System.out.println(word);
}
Using Stream.of
String sentence = "The quick fox jumps over the lazy dog. ";
String[] words = sentence
.trim()
.toUpperCase()
.split(" ");
for(String word : words) {
System.out.println(word);
}
Stream.of(sentence)
.map(String::trim)
.map(String::toUpperCase)
.map(str -> str.split(" "))
.flatMap(array -> Arrays.stream(array))
.forEach(System.out::println);
Using Stream.of
Brian Vermeer
@BrianVerm
brian@brianvermeer.nl

More Related Content

What's hot

What's hot (20)

Java(8) The Good, The Bad and the Ugly
Java(8) The Good, The Bad and the UglyJava(8) The Good, The Bad and the Ugly
Java(8) The Good, The Bad and the Ugly
 
Flask RESTful Flask HTTPAuth
Flask RESTful Flask HTTPAuthFlask RESTful Flask HTTPAuth
Flask RESTful Flask HTTPAuth
 
Rest API using Flask & SqlAlchemy
Rest API using Flask & SqlAlchemyRest API using Flask & SqlAlchemy
Rest API using Flask & SqlAlchemy
 
How to export import a mysql database via ssh in aws lightsail wordpress rizw...
How to export import a mysql database via ssh in aws lightsail wordpress rizw...How to export import a mysql database via ssh in aws lightsail wordpress rizw...
How to export import a mysql database via ssh in aws lightsail wordpress rizw...
 
Crushing React bugs with Jest and Enzyme
Crushing React bugs with Jest and EnzymeCrushing React bugs with Jest and Enzyme
Crushing React bugs with Jest and Enzyme
 
Common mistakes functional java devoxx
Common mistakes functional java devoxxCommon mistakes functional java devoxx
Common mistakes functional java devoxx
 
Common mistakes made with Functional Java
Common mistakes made with Functional JavaCommon mistakes made with Functional Java
Common mistakes made with Functional Java
 
Endevor api an introduction to the endevor application programming interface
Endevor api   an introduction to the endevor application programming interface Endevor api   an introduction to the endevor application programming interface
Endevor api an introduction to the endevor application programming interface
 
Apache FTP Server Integration
Apache FTP Server IntegrationApache FTP Server Integration
Apache FTP Server Integration
 
Server Side? Swift
Server Side? SwiftServer Side? Swift
Server Side? Swift
 
Making the most of your gradle build - Gr8Conf 2017
Making the most of your gradle build - Gr8Conf 2017Making the most of your gradle build - Gr8Conf 2017
Making the most of your gradle build - Gr8Conf 2017
 
Apache cheat sheet
Apache cheat sheetApache cheat sheet
Apache cheat sheet
 
Making the most of your gradle build - Greach 2017
Making the most of your gradle build - Greach 2017Making the most of your gradle build - Greach 2017
Making the most of your gradle build - Greach 2017
 
Infinum Android Talks #16 - Retrofit 2 by Kristijan Jurkovic
Infinum Android Talks #16 - Retrofit 2 by Kristijan JurkovicInfinum Android Talks #16 - Retrofit 2 by Kristijan Jurkovic
Infinum Android Talks #16 - Retrofit 2 by Kristijan Jurkovic
 
Retrofit 2 - O que devemos saber
Retrofit 2 - O que devemos saberRetrofit 2 - O que devemos saber
Retrofit 2 - O que devemos saber
 
JavaOne 2012 Groovy update
JavaOne 2012 Groovy updateJavaOne 2012 Groovy update
JavaOne 2012 Groovy update
 
Groovy update at SpringOne2GX 2012
Groovy update at SpringOne2GX 2012Groovy update at SpringOne2GX 2012
Groovy update at SpringOne2GX 2012
 
Dependencies Managers in C/C++. Using stdcpp 2014
Dependencies Managers in C/C++. Using stdcpp 2014Dependencies Managers in C/C++. Using stdcpp 2014
Dependencies Managers in C/C++. Using stdcpp 2014
 
Servlet 3.0
Servlet 3.0Servlet 3.0
Servlet 3.0
 
AssertJ quick introduction
AssertJ quick introductionAssertJ quick introduction
AssertJ quick introduction
 

Similar to Ten mistakes functional java

Web2py Code Lab
Web2py Code LabWeb2py Code Lab
Web2py Code Lab
Colin Su
 
Hibernate Import.Sql I18n
Hibernate Import.Sql I18nHibernate Import.Sql I18n
Hibernate Import.Sql I18n
yifi2009
 

Similar to Ten mistakes functional java (20)

Writing better functional java code devnexus
Writing better functional java code   devnexusWriting better functional java code   devnexus
Writing better functional java code devnexus
 
Java 8: the good, the bad and the ugly (Oracle Code Brussels 2017)
Java 8: the good, the bad and the ugly (Oracle Code Brussels 2017)Java 8: the good, the bad and the ugly (Oracle Code Brussels 2017)
Java 8: the good, the bad and the ugly (Oracle Code Brussels 2017)
 
Java8 tgtbatu devoxxuk18
Java8 tgtbatu devoxxuk18Java8 tgtbatu devoxxuk18
Java8 tgtbatu devoxxuk18
 
Java 8: the good, the bad and the ugly (JBCNConf 2017)
Java 8: the good, the bad and the ugly (JBCNConf 2017)Java 8: the good, the bad and the ugly (JBCNConf 2017)
Java 8: the good, the bad and the ugly (JBCNConf 2017)
 
Java8 tgtbatu javaone
Java8 tgtbatu javaoneJava8 tgtbatu javaone
Java8 tgtbatu javaone
 
Боремся с NPE вместе с Kotlin, Павел Шацких СберТех
Боремся с NPE вместе с Kotlin, Павел Шацких СберТехБоремся с NPE вместе с Kotlin, Павел Шацких СберТех
Боремся с NPE вместе с Kotlin, Павел Шацких СберТех
 
Web2py Code Lab
Web2py Code LabWeb2py Code Lab
Web2py Code Lab
 
Java Fundamentals
Java FundamentalsJava Fundamentals
Java Fundamentals
 
Silicon Valley JUG: JVM Mechanics
Silicon Valley JUG: JVM MechanicsSilicon Valley JUG: JVM Mechanics
Silicon Valley JUG: JVM Mechanics
 
The Ring programming language version 1.7 book - Part 30 of 196
The Ring programming language version 1.7 book - Part 30 of 196The Ring programming language version 1.7 book - Part 30 of 196
The Ring programming language version 1.7 book - Part 30 of 196
 
Non Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaNon Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJava
 
Hibernate Import.Sql I18n
Hibernate Import.Sql I18nHibernate Import.Sql I18n
Hibernate Import.Sql I18n
 
The Ring programming language version 1.10 book - Part 35 of 212
The Ring programming language version 1.10 book - Part 35 of 212The Ring programming language version 1.10 book - Part 35 of 212
The Ring programming language version 1.10 book - Part 35 of 212
 
JavaExamples
JavaExamplesJavaExamples
JavaExamples
 
Lambdas puzzler - Peter Lawrey
Lambdas puzzler - Peter LawreyLambdas puzzler - Peter Lawrey
Lambdas puzzler - Peter Lawrey
 
Java 8 lambda expressions
Java 8 lambda expressionsJava 8 lambda expressions
Java 8 lambda expressions
 
Productive Programming in Java 8 - with Lambdas and Streams
Productive Programming in Java 8 - with Lambdas and Streams Productive Programming in Java 8 - with Lambdas and Streams
Productive Programming in Java 8 - with Lambdas and Streams
 
Java 8 Workshop
Java 8 WorkshopJava 8 Workshop
Java 8 Workshop
 
Play!ng with scala
Play!ng with scalaPlay!ng with scala
Play!ng with scala
 
Ch ch-changes cake php2
Ch ch-changes cake php2Ch ch-changes cake php2
Ch ch-changes cake php2
 

More from Brian Vermeer

More from Brian Vermeer (10)

Stranger Danger: Your Java Attack Surface Just Got Bigger | JBCNConf 2022
Stranger Danger: Your Java Attack Surface Just Got Bigger | JBCNConf 2022Stranger Danger: Your Java Attack Surface Just Got Bigger | JBCNConf 2022
Stranger Danger: Your Java Attack Surface Just Got Bigger | JBCNConf 2022
 
Teqnation 19 - Live Hacking
Teqnation 19 - Live Hacking Teqnation 19 - Live Hacking
Teqnation 19 - Live Hacking
 
Don't be a trojan - Codemotion Amsterdam 2019
Don't be a trojan - Codemotion Amsterdam 2019Don't be a trojan - Codemotion Amsterdam 2019
Don't be a trojan - Codemotion Amsterdam 2019
 
Don't be a trojan - Java2Days 2018
Don't be a trojan - Java2Days 2018Don't be a trojan - Java2Days 2018
Don't be a trojan - Java2Days 2018
 
Don't be a Trojan
Don't be a TrojanDon't be a Trojan
Don't be a Trojan
 
Identity Theft : Developers are key
Identity Theft : Developers are keyIdentity Theft : Developers are key
Identity Theft : Developers are key
 
Identity theft jfall17
Identity theft jfall17Identity theft jfall17
Identity theft jfall17
 
Identity theft: Developers are key - JavaZone17
Identity theft: Developers are key - JavaZone17Identity theft: Developers are key - JavaZone17
Identity theft: Developers are key - JavaZone17
 
Identity theft blue4it nljug
Identity theft blue4it nljugIdentity theft blue4it nljug
Identity theft blue4it nljug
 
Identity theft: Developers are key - JFokus 2017
Identity theft: Developers are key - JFokus 2017Identity theft: Developers are key - JFokus 2017
Identity theft: Developers are key - JFokus 2017
 

Recently uploaded

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Recently uploaded (20)

TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 

Ten mistakes functional java

  • 1. Ten common mistakes made with Function Java Brian Vermeer (@BrianVerm)
  • 2.
  • 3.
  • 4.
  • 6. Doing too much in a single lambda
  • 7. Lambda Expression In computer programming, a lambda expression is a function definition that is not bound to an identifier. Anonymous functions are often:[1] • arguments being passed to higher-order functions, or • used for constructing the result of a higher-order function that needs to return a function.
  • 8. Lambda in Java Anonymous Inner functions Satisfy a Functional Interface They only exist in runtime Single Line <input> -> <output> or Block <input> -> { function body }
  • 9. Example public void execute() { Beer grolsch = new Beer("Grolsche", 4.3); String result = handleBeer(grolsch, beer -> grolsch.getName() + "-" + grolsch.getAlcohol()); System.out.println(result); } private String handleBeer(Beer beer, Function<Beer, String> func) { System.out.println("handling beer " + beer.getName()); return func.apply(beer); } //Output : Grolsche-4.3
  • 10. Don’t do Block Lambda beer -> { String name; if (beer.getName().contains(" ")) { name = beer.getName().replace(" ", ""); } else { name = beer.getName(); } try { name += Integer.parseInt(beer.getAlcoholPrecentage().toString()); } catch (NumberFormatException nfe) { name += beer.getAlcoholPrecentage(); } return name; }
  • 11. Transform to a methode private String createFullName (Beer beer){ String name; if (beer.getName().contains(" ")) { name = beer.getName().replace(" ", ""); } else { name = beer.getName(); } try { name += Integer.parseInt(beer.getAlcoholPrecentage().toString()); } catch (NumberFormatException nfe) { name += beer.getAlcoholPrecentage(); } return name; } handleBeer(grolsch, this::createFullName);
  • 13. A stream is NOT a data structure
  • 14. A stream is NOT a data structure A stream is NOT a data structure
  • 15. What is Stream ( in Java) Flow of data derived from a Collection Can create a pipeline of function that can be evaluated Intermediate result Lazy evaluated by nature Can transform data, cannot mutate data
  • 16. JAVA Streams stringLists.stream()
 .map(str -> str.toUpperCase())
 .collect(Collectors.toList()); Intermediate filter 
 distinct
 map 
 flatMap
 Terminal reduce
 collect
 toArray
 count
 max
 min
 limit 
 skip
 sorted
 peek findAny
 findFirst
 forEach
 allMatch
 anyMatch
  • 17. List<Beer> beers = getBeers();
 Stream<Beer> beerStream = beers.stream();
 
 beerStream.forEach(b ->System.out.println(b.getName())); //1 
 beerStream.forEach(b ->System.out.println(b.getAlcohol())); //2 Only use a Stream once Line 2 will give: 
 
 java.lang.IllegalStateException: stream has already been operated upon or closed
  • 18. public Stream<Beer> getMeMyBeers() public void execute() { getMeMyBeers() //don’t know if it is consumed yet!!!! … } Don’t return a Stream
  • 19. Not Consuming a Stream
  • 20.
  • 21.
  • 22.
  • 23.
  • 24. List<Beer> beers = List.of(new Beer("Heineken", 5.2), new Beer("Delirium Tremens", 9.0), new Beer("Amstel", 5.1)); beers.stream()
 .limit(10)
 .map(i -> i.getAlcohol())
 .peek(i -> {
 if (i > 7.0)
 throw new RuntimeException();
 }); Consume the stream
  • 25.
  • 26. List<Beer> beers = List.of(new Beer("Heineken", 5.2), new Beer("Delirium Tremens", 9.0), new Beer("Amstel", 5.1)); beers.stream()
 .limit(10)
 .map(i -> i.getAlcohol())
 .peek(i -> {
 if (i > 7.0)
 throw new RuntimeException();
 }) .forEach(System.out::println); Consume the stream 5.2 Exception in thread "main" java.lang.RuntimeException
  • 28. Functional Programming In computer science, functional programming is a programming paradigma style of building the structure and elements of computer programs that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data. It is a declarative programming paradigm, which means programming is done with expressions or declarations instead of statements. — wikipedia
  • 29.
  • 30. – Kevlin Henney “Asking a question should not change the answer, nor should asking it twice”
  • 31. Immutable objects Less moving parts Easier to reason about code No need to keep a mental map of the state an object is in.
  • 32. Stream cannot mutate private final List<Beer> beers = List.of(new Beer("Heineken", 5.2), new Beer("Amstel", 5.1)); public void execute() { List<Beer> beersNew = beers.stream() .map(beer -> beer.setName(“foo”)) //not allowed .collect(Collectors.toList()); }
  • 33. Stream should not mutate ! private class Beer { String name; Double alcohol; public Beer setName(String name){ this.name = name; return this; } } private final List<Beer> beers = List.of(new Beer("Heineken", 5.2), new Beer("Amstel", 5.1)); public void execute() { List<Beer> beersNew = beers.stream() .map(beer -> beer.setName("foo")) .collect(Collectors.toList()); System.out.println(beers); System.out.println(beersNew); }
  • 34. Stream should not mutate ! private class Beer { String name; Double alcohol; public Beer setName(String name){ this.name = name; return this; } } private final List<Beer> beers = List.of(new Beer("Heineken", 5.2), new Beer("Amstel", 5.1)); public void execute() { List<Beer> beersNew = beers.stream() .map(beer -> beer.setName("foo")) .collect(Collectors.toList()); System.out.println(beers); System.out.println(beersNew); }
  • 35. Return a new copy private class Beer { String name; Double alcohol; public Beer withName(String name){ return new Beer(name, this.alcohol); } } private final List<Beer> beers = List.of(new Beer("Heineken", 5.2), new Beer("Amstel", 5.1)); public void execute() { List<Beer> beersNew = beers.stream() .map(beer -> beer.withName("foo")) .collect(Collectors.toList()); System.out.println(beers); System.out.println(beersNew); }
  • 37. forEach() Terminal functional on a stream. Takes a consumer. Can be used to apply side effects. for-loop without the external iterator
  • 38. simple forEach example List<String> names = List.of("James", "Trisha", "Joshua", "Jessica","Simon", “Heather"); names.stream() .map(String::toUpperCase) .forEach(System.out::println);
  • 39. mutation with forEach List<Beer> beers = List.of(new Beer("Heineken", 5.2), new Beer("Amstel", 5.1)); beers.stream() .forEach(beer -> beer.setAlcohol(0.0));
  • 40. overusing forEach private class Beer { String name; Double alcohol; List<String> reviews; Integer rating; } List<Beer> beers = List.of(new Beer("Heineken", 5.2), new Beer("Amstel", 5.1)); //enrich with ratings beers.stream().forEach(beer -> beer.setRating(findRating(beer.getName()))); //enrich with reviews beers.stream().forEach(beer -> beer.setReviews(findReviews(beer.getName()))); …
  • 42. Assignment Beers -> Brewer -> Country I want the first 3 unique brewers countries from the beer library as comma separated String beerLib.stream() .map(Beer::getBrewer) .distinct() .limit(3) .map(Brewer::getCountry) .map(String::toUpperCase) .collect(Collectors.joining(“,”));
  • 43. Assignment Beers -> Brewer -> Country I want the first 3 unique brewers countries from the beer library as comma separated String beerLib.stream() .map(Beer::getBrewer) .distinct() .limit(3) .map(Brewer::getCountry) .map(String::toUpperCase) .collect(Collectors.joining(“,”)); // wrong
  • 44. Assignment Beers -> Brewer -> Country I want the first 3 unique brewers countries from the beer library as comma separated String beerLib.stream() .map(Beer::getBrewer) .map(Brewer::getCountry) .map(String::toUpperCase) .distinct() .limit(3) .collect(Collectors.joining(“,”)); // correct
  • 45. Infinite stream IntStream.iterate(0, i -> ( i + 1) % 2)
 .distinct()
 .limit(10)
 .forEach(i -> System.out.println(i));
  • 46. Infinite stream IntStream.iterate(0, i -> ( i + 1) % 2)
 .distinct()
 .limit(10)
 .forEach(i -> System.out.println(i));
 // will run forever IntStream.iterate(0, i -> ( i + 1) % 2)
 .limit(10)
 .distinct()
 .forEach(i -> System.out.println(i)); //will terminate
  • 47. Infinite stream IntStream.iterate(0, i -> ( i + 1) % 2)
 .parallel() .distinct()
 .limit(10)
 .forEach(i -> System.out.println(i));
 // will run forever on all threads.
  • 48. Solution 1. Look closely at the order of operations
 - prevent incorrect answers
 
 2. Only use infinite streams when absolutely necessary. rather use: 
 IntStream.range(0,10); IntStream.rangeClosed(0,10); IntStream.iterate(0, i -> i < 10, i -> i + 1); //java 9 and up
  • 50. Optional Java’s implementation of the Maybe Monad Encapsulation to handle possible null value Consider it a wrapper where a value can be absent Force the user to unpack the Optional before using it.
  • 51. Optional Optional<String> c = null //please avoid this
  • 52. public void execute() { Optional<String> maybeString = getText(); String unpacked = maybeString.get(); } Unpack Optional
  • 53. public void execute() { Optional<String> maybeString = getText(); String unpacked = maybeString.get(); } Unpack Optional NoSuchElementException
  • 54. public void execute() { Optional<String> maybeString = getText(); String unpacked = maybeString.get(); } Unpack Optional public void execute() { Optional<String> maybeString = getText(); if (maybeString.isPresent()) { String unpacked = maybeString.get(); } } NoSuchElementException
  • 55. Unpack Optional public void execute() { Optional<String> maybeString = getText(); maybeString.ifPresent( str -> /* doSomething */ ); } public void execute() { Optional<String> maybeString = getText(); maybeString.map(str -> str + “."); }
  • 57. Alternative flow - orElse() - orElseGet() - orElseThrow()
  • 58. orElseThrow public void execute() {
 Optional<String> maybeString = Optional.empty();
 maybeString
 .map(this::runIfExist)
 .orElseThrow(() -> new RuntimeException("Optional was empty"));
 }
  • 59. orElse public void execute() {
 Optional<String> maybeString = Optional.of("foo");
 String newString = maybeString
 .map(this::runIfExist)
 .orElse(runIfEmpty());
 System.out.println(newString);
 }
 private String runIfExist(String str) {
 System.out.println("only run if optional is filled ");
 return str;
 }
 private String runIfEmpty() {
 System.out.println("only run if empty");
 return "empty";
 }
  • 60. orElse public void execute() {
 Optional<String> maybeString = Optional.of("foo");
 String newString = maybeString
 .map(this::runIfExist)
 .orElse(runIfEmpty());
 System.out.println(newString);
 }
 private String runIfExist(String str) {
 System.out.println("only run if optional is filled ");
 return str;
 }
 private String runIfEmpty() {
 System.out.println("only run if empty");
 return "empty";
 } only run if optional is filled only run if empty foo
  • 61. orElseGet public void execute() {
 Optional<String> maybeString = Optional.of("foo");
 String newString = maybeString
 .map(this::runIfExist)
 .orElseGet(() -> runIfEmpty());
 System.out.println(newString);
 }
 private String runIfExist(String str) {
 System.out.println("only run if optional is filled ");
 return str;
 }
 private String runIfEmpty() {
 System.out.println("only run if empty");
 return "empty";
 }
  • 62. orElseGet public void execute() {
 Optional<String> maybeString = Optional.of("foo");
 String newString = maybeString
 .map(this::runIfExist)
 .orElseGet(() -> runIfEmpty());
 System.out.println(newString);
 }
 private String runIfExist(String str) {
 System.out.println("only run if optional is filled ");
 return str;
 }
 private String runIfEmpty() {
 System.out.println("only run if empty");
 return "empty";
 } only run if optional is filled foo
  • 63. what else? - When using orElse(x), make sure x doesn’t contain any side effects - Only use orElse() to assign a default value - Use orElseGet() to run an alternative flow
  • 65. Checked Exceptions & Lambda public Beer doSomething(Beer beer) throws IsEmptyException { …} Function <Beer,Beer> fBeer = beer -> doSomething(beer) 

  • 66. Checked Exceptions & Lambda public Beer doSomething(Beer beer) throws IsEmptyException { …} Function <Beer,Beer> fBeer = beer -> doSomething(beer) 

  • 67. Checked Exceptions & Lambda public Beer doSomething(Beer beer) throws IsEmptyException { …} beerLib.stream() .map(beer -> {
 try{
 return doSomething(beer);
 } catch (IsEmptyException e) {
 throw new RuntimeException(e);
 }
 };) .collect(Collectors.toList()); //not very pretty
  • 68. Checked Exceptions & Lambda public Beer doSomething(Beer beer) throws IsEmptyException { …} private Beer wrappedDoSomeThing(Beer beer) {
 try{
 return doSomething(beer);
 } catch (IsEmptyException e) {
 throw new RuntimeException(e);
 }
 } beerLib.stream() .map(this::wrappedDoSomeThing) .collect(Collectors.toList());
  • 69. Exception Utility @FunctionalInterface
 public interface CheckedFunction<T, R> {
 public R apply(T t) throws Throwable;
 } public static <T, R> Function<T, R> wrap(CheckedFunction<T, R> function) {
 return t -> {
 try {
 return function.apply(t);
 } catch (Throwable ex) {
 throw new RuntimeException(ex);
 }
 };
 }; beerLib.stream() .map(beer -> wrap(doSomething(beer))) .collect(Collectors.toList());
  • 70. Either type public class Either<L, R> { private final L left; private final R right; private Either(L left, R right) { this.left = left; this.right = right; } public static <L,R> Either<L,R> Left( L value) { return new Either(value, null); } public static <L,R> Either<L,R> Right( R value) { return new Either(null, value); } … }
  • 71. Either type private Either<Exception, String> canGoWrong(Integer input) { if (input > 10) { return Either.Left(new RuntimeException("larger then 10")); } return Either.Right("["+input+"]"); } List<Either<Exception, String>> canGoWrongs = IntStream.range(0,12) .mapToObj(i -> canGoWrong(i)) .collect(Collectors.toList());
  • 72. Either type private Either<Exception, String> canGoWrong(Integer input) { if (input > 10) { return Either.Left(new RuntimeException("larger then 10")); } return Either.Right(“["+input+"]"); } List<Either<Exception, String>> canGoWrongs = IntStream.range(0,12) .mapToObj(i -> canGoWrong(i)) .collect(Collectors.toList()); canGoWrongs.stream() .map(e -> e.mapRight(s -> s.toUpperCase())) .flatMap(o -> o.map(Stream::of).orElseGet(Stream::empty)) .forEach(System.out::println);
  • 74. //java 9 List myList = List.of(1,2,3,4,5) //pre Java9 List myList = Arrays.asList(new String[] {“a”,"b","c"}); Creating collections
  • 75. //java 9 List myList = List.of(1,2,3,4,5) //pre Java9 List myList = Arrays.asList(new String[] {"a","b","c"}); // since Java 8 List myList = Stream.of("a","b","c","d").collect(Collectors.toList()); Creating collections
  • 76. private Beer foo(){...} private Beer bar(){...} private Beer fooBar(){…} Beer myBeer = new Beer(); Beer result = fooBar(bar(foo(myBeer))); Using Stream.of
  • 77. private Beer foo(){...} private Beer bar(){...} private Beer fooBar(){…} Beer myBeer = new Beer(); Beer result = fooBar(bar(foo(myBeer))); Using Stream.of Beer result = Stream.of(myBeer) .map(this::foo)
 .map(this::bar)
 .map(this::fooBar)
 .findFirst().get();
  • 78. String sentence = "The quick fox jumps over the lazy dog. "; String[] words = sentence .trim() .toUpperCase() .split(" "); for(String word : words) { System.out.println(word); } Using Stream.of
  • 79. String sentence = "The quick fox jumps over the lazy dog. "; String[] words = sentence .trim() .toUpperCase() .split(" "); for(String word : words) { System.out.println(word); } Stream.of(sentence) .map(String::trim) .map(String::toUpperCase) .map(str -> str.split(" ")) .flatMap(array -> Arrays.stream(array)) .forEach(System.out::println); Using Stream.of