SlideShare a Scribd company logo
1 of 82
Download to read offline
Writing better
Functional Java code@BrianVerm
@BrianVerm
@BrianVerm
@BrianVerm
@BrianVerm
Brian Vermeer
Developer Advocate
Don’t do to much in a single lambda
@BrianVerm
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.
@BrianVerm
Lambda in Java
Anonymous Inner functions
Satisfy a Functional Interface
They only exist in runtime
Single Line <input> -> <output> or Block <input> -> { function body }
@BrianVerm
Example
@BrianVerm
public void execute() {
Beer grolsch = new Beer("Grolsch", 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 : Grolsch-4.3
Example
@BrianVerm
public void execute() {
Beer grolsch = new Beer("Grolsch", 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 : Grolsch-4.3
Don’t do Block Lambda
@BrianVerm
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
@BrianVerm
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;
}
String result = handleBeer(grolsch, this::createFullName);
Returning a Stream
@BrianVerm
A stream is NOT a data
structure
@BrianVerm
A stream is NOT a data
structure
@BrianVerm
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
@BrianVerm
JAVA Streams
@BrianVerm
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
@BrianVerm
public Stream<Beer> getMeMyBeers()
public void execute() {
getMeMyBeers() //don’t know if it is consumed yet!!!!
…
}
Be careful with returning a Stream
@BrianVerm
Returning a Stream
Private intermediate function
When new stream is created every time
When result is very large or might be infinite
By default return a collection
@BrianVerm
Mutable Object
@BrianVerm
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
@BrianVerm
@BrianVerm
@BrianVerm
– 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.
@BrianVerm
Stream cannot mutate
@BrianVerm
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 !
@BrianVerm
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 !
@BrianVerm
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
@BrianVerm
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
@BrianVerm
forEach()
Terminal functional on a stream.
Takes a consumer.
Can be used to apply side effects.
for-loop without the external iterator
@BrianVerm
simple forEach example
@BrianVerm
List<String> names = List.of("James", "Trisha", "Joshua",
"Jessica","Simon", “Heather”, “Roberto”);
names.stream()
.map(String::toUpperCase)
.forEach(System.out::println);
mutation with forEach
@BrianVerm
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
@BrianVerm
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
@BrianVerm
Assignment
Beers -> Brewer -> Country
I want the first 3 unique brewers countries from the beer library as comma separated String
@BrianVerm
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
@BrianVerm
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
@BrianVerm
beerLib.stream()
.map(Beer::getBrewer)
.map(Brewer::getCountry)
.map(String::toUpperCase)
.distinct()
.limit(3)
.collect(Collectors.joining(“,”));
// correct
Infinite stream
@BrianVerm
IntStream.iterate(0, i -> ( i + 1) % 2)

.distinct()

.limit(10)

.forEach(i -> System.out.println(i));
Infinite stream
@BrianVerm
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
@BrianVerm
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: 

@BrianVerm
IntStream.range(0,10);
IntStream.rangeClosed(0,10);
IntStream.iterate(0, i -> i < 10, i -> i + 1); //java 9 and up
Create higher-order functions
@BrianVerm
Higher-Order function
Taking a function as a parameter of a method
Insert behaviour instead of just data
A new level of abstraction
Reduce boilerplate / duplicate code
@BrianVerm
Duplicate code
@BrianVerm
private void logUpper(String str) {

//super interesting code

System.out.println(str.toUpperCase());

//even more interesting code

}



private void logLower(String str) {

//super interesting code

System.out.println(str.toLowerCase());

//even more interesting code

}
Insert behaviour
@BrianVerm
private void logUpper(String string) {

doSuperCoolStuff(string, s -> s.toUpperCase());

}



private void logLower(String string) {

doSuperCoolStuff(string, s -> s.toLowerCase());

}



private void doFoo(String str, Function<String, String> func) {

//super interesting code

System.out.println(func.apply(str));

//even more interesting code

}
Real situation (Webshop Basket)
MongoDB primary (read/write), multiple secondary (read)
Writing only on the primary
Mutating a basket:
Read from Primary

Edit

Run rule engine

Save to Primary

@BrianVerm
Real situation (Webshop Basket)
MongoDB primary (read/write), multiple secondary (read)
Writing only on the primary
Mutating a basket:
Read from Primary

Edit

Run rule engine

Save to Primary

@BrianVerm
Mutator
@BrianVerm
public void mutatorById(String id, Consumer<Basket> action) {
Basket basket = repoPrimary.findById(id);
action.accept(basket);
RuleEngine.run(basket)
repoPrimary.save(basket);
}
Mutator
@BrianVerm
public void mutatorById(String id, Consumer<Basket> action) {
Basket basket = repoPrimary.findById(id);
action.accept(basket);
RuleEngine.run(basket)
repoPrimary.save(basket);
}
public void addItem(String uuid, Item item) {
mutatorById(uuid, basket -> basket.addItem(item));
}
public void removeItem(String uuid, Item item) {
mutatorById(uuid, basket -> basket.removeItem(item));
}
Getting an Optional
@BrianVerm
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.
@BrianVerm
Optional
@BrianVerm
Optional<String> c = null //please avoid this
public void execute() {
Optional<String> maybeString = getText();
String unpacked = maybeString.get();
}
Unpack Optional
@BrianVerm
public void execute() {
Optional<String> maybeString = getText();
String unpacked = maybeString.get();
}
Unpack Optional
@BrianVerm
NoSuchElementException
public void execute() {
Optional<String> maybeString = getText();
String unpacked = maybeString.get();
}
Unpack Optional
@BrianVerm
public void execute() {
Optional<String> maybeString = getText();
if (maybeString.isPresent()) {
String unpacked = maybeString.get();
}
}
NoSuchElementException
Unpack Optional
@BrianVerm
public void execute() {
Optional<String> maybeString = getText();
maybeString.ifPresent( str -> /* doSomething */ );
}
public void execute() {
Optional<String> maybeString = getText();
maybeString.map(str -> str + “.");
}
What else ..??
@BrianVerm
Alternative flow
- orElse()
- orElseGet()
- orElseThrow()
@BrianVerm
orElseThrow
@BrianVerm
public void execute() {

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

maybeString

.map(this::runIfExist)

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

}
orElse
@BrianVerm
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
@BrianVerm
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
@BrianVerm
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
@BrianVerm
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
@BrianVerm
List of Optionals
@BrianVerm
beerLib.stream()
.map(Beer::getDescription) //returns optional
List of Optionals
@BrianVerm
//java 8 style
beerLib.stream()
.map(Beer::getDescription) //returns optional
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(System.out::println);
List of Optionals
@BrianVerm
//java 8 flatMap
beerLib.stream()
.map(Beer::getDescription) //returns optional
.flatMap(o -> o.map(Stream::of).orElse(Stream.empty()))
.forEach(System.out::println);
List of Optionals
@BrianVerm
//java 9 flatMap
beerLib.stream()
.map(Beer::getDescription) //returns optional
.flatMap(Optional::stream)
.forEach(System.out::println);
Exceptions
@BrianVerm
Checked Exceptions & Lambda
@BrianVerm


public Beer doSomething(Beer beer) throws IsEmptyException { …}
Function <Beer,Beer> fBeer = beer -> doSomething(beer)
Checked Exceptions & Lambda
@BrianVerm
public Beer doSomething(Beer beer) throws IsEmptyException { …}
Function <Beer,Beer> fBeer = beer -> doSomething(beer)
Checked Exceptions & Lambda
@BrianVerm
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
@BrianVerm
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
@BrianVerm
@FunctionalInterface

public interface CheckedFunction<T, R> {

public R apply(T t) throws Exception;

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

return t -> {

try {

return function.apply(t);

} catch (Exception ex) {

throw new RuntimeException(ex);

}

};

};
beerLib.stream()
.map(wrap(beer -> doSomething(beer)))
.collect(Collectors.toList());
Either type
@BrianVerm
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
@BrianVerm
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
@BrianVerm
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);
Try
- Failure (Exception)
- Success (Type)
- VAVR
@BrianVerm
Try
- Failure (Exception)
- Success (Type)
- VAVR
@BrianVerm
List<Try<String>> output = teams.stream()
.map(CheckedFunction1.liftTry(this::mayThrowException))
.collect(Collectors.toList());
@BrianVerm
@BrianVerm
Brian Vermeer
@BrianVerm
brianvermeer@snyk.io

More Related Content

What's hot

Flask patterns
Flask patternsFlask patterns
Flask patterns
it-people
 
VPN Access Runbook
VPN Access RunbookVPN Access Runbook
VPN Access Runbook
Taha Shakeel
 

What's hot (19)

Ten mistakes functional java
Ten mistakes functional javaTen mistakes functional java
Ten mistakes functional java
 
Server Side? Swift
Server Side? SwiftServer Side? Swift
Server Side? Swift
 
Flask SQLAlchemy
Flask SQLAlchemy Flask SQLAlchemy
Flask SQLAlchemy
 
Rest API using Flask & SqlAlchemy
Rest API using Flask & SqlAlchemyRest API using Flask & SqlAlchemy
Rest API using Flask & SqlAlchemy
 
In-depth analysis of Kotlin Flows
In-depth analysis of Kotlin FlowsIn-depth analysis of Kotlin Flows
In-depth analysis of Kotlin Flows
 
Http basics
Http basicsHttp basics
Http basics
 
Javascript tutorial RESTful APIs for Free
Javascript tutorial RESTful APIs for FreeJavascript tutorial RESTful APIs for Free
Javascript tutorial RESTful APIs for Free
 
Flask patterns
Flask patternsFlask patterns
Flask patterns
 
Flask RESTful Flask HTTPAuth
Flask RESTful Flask HTTPAuthFlask RESTful Flask HTTPAuth
Flask RESTful Flask HTTPAuth
 
Overpsss API / Overpass-Turbo
Overpsss API / Overpass-TurboOverpsss API / Overpass-Turbo
Overpsss API / Overpass-Turbo
 
Filling the flask
Filling the flaskFilling the flask
Filling the flask
 
Flask - Backend com Python - Semcomp 18
Flask - Backend com Python - Semcomp 18Flask - Backend com Python - Semcomp 18
Flask - Backend com Python - Semcomp 18
 
Flask Basics
Flask BasicsFlask Basics
Flask Basics
 
Apache cassandra - future without boundaries (part3)
Apache cassandra - future without boundaries (part3)Apache cassandra - future without boundaries (part3)
Apache cassandra - future without boundaries (part3)
 
Flask – Python
Flask – PythonFlask – Python
Flask – Python
 
Python RESTful webservices with Python: Flask and Django solutions
Python RESTful webservices with Python: Flask and Django solutionsPython RESTful webservices with Python: Flask and Django solutions
Python RESTful webservices with Python: Flask and Django solutions
 
Getting Started-with-Laravel
Getting Started-with-LaravelGetting Started-with-Laravel
Getting Started-with-Laravel
 
Debugging on Rails. Mykhaylo Sorochan
Debugging on Rails. Mykhaylo SorochanDebugging on Rails. Mykhaylo Sorochan
Debugging on Rails. Mykhaylo Sorochan
 
VPN Access Runbook
VPN Access RunbookVPN Access Runbook
VPN Access Runbook
 

Similar to Writing better functional java code - devnexus

30 5 Database Jdbc
30 5 Database Jdbc30 5 Database Jdbc
30 5 Database Jdbc
phanleson
 
For this lab, you will write the following filesAbstractDataCalc.pdf
For this lab, you will write the following filesAbstractDataCalc.pdfFor this lab, you will write the following filesAbstractDataCalc.pdf
For this lab, you will write the following filesAbstractDataCalc.pdf
alokindustries1
 

Similar to Writing better functional java code - devnexus (20)

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
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
 
Java8 tgtbatu javaone
Java8 tgtbatu javaoneJava8 tgtbatu javaone
Java8 tgtbatu javaone
 
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)
 
JDBC Tutorial
JDBC TutorialJDBC Tutorial
JDBC Tutorial
 
30 5 Database Jdbc
30 5 Database Jdbc30 5 Database Jdbc
30 5 Database Jdbc
 
For this lab, you will write the following filesAbstractDataCalc.pdf
For this lab, you will write the following filesAbstractDataCalc.pdfFor this lab, you will write the following filesAbstractDataCalc.pdf
For this lab, you will write the following filesAbstractDataCalc.pdf
 
3 database-jdbc(1)
3 database-jdbc(1)3 database-jdbc(1)
3 database-jdbc(1)
 
Lambdas puzzler - Peter Lawrey
Lambdas puzzler - Peter LawreyLambdas puzzler - Peter Lawrey
Lambdas puzzler - Peter Lawrey
 
Java 8 Workshop
Java 8 WorkshopJava 8 Workshop
Java 8 Workshop
 
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
 
My java file
My java fileMy java file
My java file
 
Aimaf
AimafAimaf
Aimaf
 
Lambda Functions in Java 8
Lambda Functions in Java 8Lambda Functions in Java 8
Lambda Functions in Java 8
 
Spring boot
Spring boot Spring boot
Spring boot
 
1.1 Intro to WinDDI.pdf
1.1 Intro to WinDDI.pdf1.1 Intro to WinDDI.pdf
1.1 Intro to WinDDI.pdf
 
Sailing with Java 8 Streams
Sailing with Java 8 StreamsSailing with Java 8 Streams
Sailing with Java 8 Streams
 
SQLite Techniques
SQLite TechniquesSQLite Techniques
SQLite Techniques
 
Java
JavaJava
Java
 

More from Brian Vermeer

More from Brian Vermeer (11)

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
 
Writing better functional java code devnexus
Writing better functional java code   devnexusWriting better functional java code   devnexus
Writing better functional java code devnexus
 
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

%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
masabamasaba
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
masabamasaba
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
masabamasaba
 

Recently uploaded (20)

%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
tonesoftg
tonesoftgtonesoftg
tonesoftg
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
 

Writing better functional java code - devnexus

  • 6. Don’t do to much in a single lambda @BrianVerm
  • 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. @BrianVerm
  • 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 } @BrianVerm
  • 9. Example @BrianVerm public void execute() { Beer grolsch = new Beer("Grolsch", 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 : Grolsch-4.3
  • 10. Example @BrianVerm public void execute() { Beer grolsch = new Beer("Grolsch", 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 : Grolsch-4.3
  • 11. Don’t do Block Lambda @BrianVerm 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; }
  • 12. Transform to a methode @BrianVerm 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; } String result = handleBeer(grolsch, this::createFullName);
  • 14. A stream is NOT a data structure @BrianVerm
  • 15. A stream is NOT a data structure @BrianVerm A stream is NOT a data structure
  • 16. 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 @BrianVerm
  • 17. JAVA Streams @BrianVerm 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
  • 18. 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 @BrianVerm
  • 19. public Stream<Beer> getMeMyBeers() public void execute() { getMeMyBeers() //don’t know if it is consumed yet!!!! … } Be careful with returning a Stream @BrianVerm
  • 20. Returning a Stream Private intermediate function When new stream is created every time When result is very large or might be infinite By default return a collection @BrianVerm
  • 22. 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 @BrianVerm
  • 24. @BrianVerm – Kevlin Henney “Asking a question should not change the answer, nor should asking it twice”
  • 25. Immutable objects Less moving parts Easier to reason about code No need to keep a mental map of the state an object is in. @BrianVerm
  • 26. Stream cannot mutate @BrianVerm 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()); }
  • 27. Stream should not mutate ! @BrianVerm 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); }
  • 28. Stream should not mutate ! @BrianVerm 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); }
  • 29. Return a new copy @BrianVerm 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); }
  • 31. forEach() Terminal functional on a stream. Takes a consumer. Can be used to apply side effects. for-loop without the external iterator @BrianVerm
  • 32. simple forEach example @BrianVerm List<String> names = List.of("James", "Trisha", "Joshua", "Jessica","Simon", “Heather”, “Roberto”); names.stream() .map(String::toUpperCase) .forEach(System.out::println);
  • 33. mutation with forEach @BrianVerm List<Beer> beers = List.of(new Beer("Heineken", 5.2), new Beer("Amstel", 5.1)); beers.stream() .forEach(beer -> beer.setAlcohol(0.0));
  • 34. overusing forEach @BrianVerm 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()))); …
  • 36. Assignment Beers -> Brewer -> Country I want the first 3 unique brewers countries from the beer library as comma separated String @BrianVerm beerLib.stream() .map(Beer::getBrewer) .distinct() .limit(3) .map(Brewer::getCountry) .map(String::toUpperCase) .collect(Collectors.joining(“,”));
  • 37. Assignment Beers -> Brewer -> Country I want the first 3 unique brewers countries from the beer library as comma separated String @BrianVerm beerLib.stream() .map(Beer::getBrewer) .distinct() .limit(3) .map(Brewer::getCountry) .map(String::toUpperCase) .collect(Collectors.joining(“,”)); // wrong
  • 38. Assignment Beers -> Brewer -> Country I want the first 3 unique brewers countries from the beer library as comma separated String @BrianVerm beerLib.stream() .map(Beer::getBrewer) .map(Brewer::getCountry) .map(String::toUpperCase) .distinct() .limit(3) .collect(Collectors.joining(“,”)); // correct
  • 39. Infinite stream @BrianVerm IntStream.iterate(0, i -> ( i + 1) % 2)
 .distinct()
 .limit(10)
 .forEach(i -> System.out.println(i));
  • 40. Infinite stream @BrianVerm 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
  • 41. Infinite stream @BrianVerm IntStream.iterate(0, i -> ( i + 1) % 2)
 .parallel() .distinct()
 .limit(10)
 .forEach(i -> System.out.println(i));
 // will run forever on all threads.
  • 42. Solution 1. Look closely at the order of operations
 - prevent incorrect answers
 
 2. Only use infinite streams when absolutely necessary. rather use: 
 @BrianVerm IntStream.range(0,10); IntStream.rangeClosed(0,10); IntStream.iterate(0, i -> i < 10, i -> i + 1); //java 9 and up
  • 44. Higher-Order function Taking a function as a parameter of a method Insert behaviour instead of just data A new level of abstraction Reduce boilerplate / duplicate code @BrianVerm
  • 45. Duplicate code @BrianVerm private void logUpper(String str) {
 //super interesting code
 System.out.println(str.toUpperCase());
 //even more interesting code
 }
 
 private void logLower(String str) {
 //super interesting code
 System.out.println(str.toLowerCase());
 //even more interesting code
 }
  • 46. Insert behaviour @BrianVerm private void logUpper(String string) {
 doSuperCoolStuff(string, s -> s.toUpperCase());
 }
 
 private void logLower(String string) {
 doSuperCoolStuff(string, s -> s.toLowerCase());
 }
 
 private void doFoo(String str, Function<String, String> func) {
 //super interesting code
 System.out.println(func.apply(str));
 //even more interesting code
 }
  • 47. Real situation (Webshop Basket) MongoDB primary (read/write), multiple secondary (read) Writing only on the primary Mutating a basket: Read from Primary
 Edit
 Run rule engine
 Save to Primary
 @BrianVerm
  • 48. Real situation (Webshop Basket) MongoDB primary (read/write), multiple secondary (read) Writing only on the primary Mutating a basket: Read from Primary
 Edit
 Run rule engine
 Save to Primary
 @BrianVerm
  • 49. Mutator @BrianVerm public void mutatorById(String id, Consumer<Basket> action) { Basket basket = repoPrimary.findById(id); action.accept(basket); RuleEngine.run(basket) repoPrimary.save(basket); }
  • 50. Mutator @BrianVerm public void mutatorById(String id, Consumer<Basket> action) { Basket basket = repoPrimary.findById(id); action.accept(basket); RuleEngine.run(basket) repoPrimary.save(basket); } public void addItem(String uuid, Item item) { mutatorById(uuid, basket -> basket.addItem(item)); } public void removeItem(String uuid, Item item) { mutatorById(uuid, basket -> basket.removeItem(item)); }
  • 52. 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. @BrianVerm
  • 53. Optional @BrianVerm Optional<String> c = null //please avoid this
  • 54. public void execute() { Optional<String> maybeString = getText(); String unpacked = maybeString.get(); } Unpack Optional @BrianVerm
  • 55. public void execute() { Optional<String> maybeString = getText(); String unpacked = maybeString.get(); } Unpack Optional @BrianVerm NoSuchElementException
  • 56. public void execute() { Optional<String> maybeString = getText(); String unpacked = maybeString.get(); } Unpack Optional @BrianVerm public void execute() { Optional<String> maybeString = getText(); if (maybeString.isPresent()) { String unpacked = maybeString.get(); } } NoSuchElementException
  • 57. Unpack Optional @BrianVerm public void execute() { Optional<String> maybeString = getText(); maybeString.ifPresent( str -> /* doSomething */ ); } public void execute() { Optional<String> maybeString = getText(); maybeString.map(str -> str + “."); }
  • 59. Alternative flow - orElse() - orElseGet() - orElseThrow() @BrianVerm
  • 60. orElseThrow @BrianVerm public void execute() {
 Optional<String> maybeString = Optional.empty();
 maybeString
 .map(this::runIfExist)
 .orElseThrow(() -> new RuntimeException("Optional was empty"));
 }
  • 61. orElse @BrianVerm 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";
 }
  • 62. orElse @BrianVerm 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
  • 63. orElseGet @BrianVerm 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";
 }
  • 64. orElseGet @BrianVerm 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
  • 65. 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 @BrianVerm
  • 67. List of Optionals @BrianVerm //java 8 style beerLib.stream() .map(Beer::getDescription) //returns optional .filter(Optional::isPresent) .map(Optional::get) .forEach(System.out::println);
  • 68. List of Optionals @BrianVerm //java 8 flatMap beerLib.stream() .map(Beer::getDescription) //returns optional .flatMap(o -> o.map(Stream::of).orElse(Stream.empty())) .forEach(System.out::println);
  • 69. List of Optionals @BrianVerm //java 9 flatMap beerLib.stream() .map(Beer::getDescription) //returns optional .flatMap(Optional::stream) .forEach(System.out::println);
  • 71. Checked Exceptions & Lambda @BrianVerm 
 public Beer doSomething(Beer beer) throws IsEmptyException { …} Function <Beer,Beer> fBeer = beer -> doSomething(beer)
  • 72. Checked Exceptions & Lambda @BrianVerm public Beer doSomething(Beer beer) throws IsEmptyException { …} Function <Beer,Beer> fBeer = beer -> doSomething(beer)
  • 73. Checked Exceptions & Lambda @BrianVerm 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
  • 74. Checked Exceptions & Lambda @BrianVerm 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());
  • 75. Exception Utility @BrianVerm @FunctionalInterface
 public interface CheckedFunction<T, R> {
 public R apply(T t) throws Exception;
 } public static <T, R> Function<T, R> wrap(CheckedFunction<T, R> function) {
 return t -> {
 try {
 return function.apply(t);
 } catch (Exception ex) {
 throw new RuntimeException(ex);
 }
 };
 }; beerLib.stream() .map(wrap(beer -> doSomething(beer))) .collect(Collectors.toList());
  • 76. Either type @BrianVerm 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); } … }
  • 77. Either type @BrianVerm 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());
  • 78. Either type @BrianVerm 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);
  • 79. Try - Failure (Exception) - Success (Type) - VAVR @BrianVerm
  • 80. Try - Failure (Exception) - Success (Type) - VAVR @BrianVerm List<Try<String>> output = teams.stream() .map(CheckedFunction1.liftTry(this::mayThrowException)) .collect(Collectors.toList());