SlideShare a Scribd company logo
Ian Robertson
Lambda Chops
Recipes for Simpler, More Expressive Code
Agenda
● Lambda review
● Lambda tricks
● Lack of exception transparency
● Turning patterns into libraries
● Adding type safety with lambdas
● API design best practices
About Me
● Application Architect at Myriad Genetics
● 17 years experience of working on large-scale
Java projects
● Twitter: @nainostrebor
● https://github.com/irobertson
● JavaOne Rockstar
Disclaimer
● Not all code shown in this talk is optimally
performant.
● Neither is it particularly non-performant.
● Most of the time, expressiveness trumps
performance.
Lambdas
● New in Java 8.
● More than just anon inner classes on steroids
● Represented by single method interface.
Function<String, Integer> length = (String s) -> { return s.length(); };
…................................................ = s -> s.length();
…................................................ = String::length;
Primary advertised use case: streams
● Much more expressive
● Multi-core friendly
Map<City, Double> engineerSalaryByCity = employees.stream()
.filter(e -> e.getJobType().equals("Engineer"))
.collect(Collectors.groupingBy(
Employee::getCity,
Collectors.averagingDouble(Employee::getSalary)));
Lambdas allow us to refer to an action
without actually doing the action.
Lambda trick: Null-Safe Navigation
● Groovy folks can write
employee?.getAddress()?.getCity()?.toString()
● If anything along the way is null, returns null
● Java equivalent:
(employee != null
&& employee.getAddress() != null
&& employee.getAddress().getCity() != null)
? employee.getAddress().getCity().toString()
: null;
Lambda trick: Null-Safe Navigation
● Alternative – (ab)use Optional
String cityName = Optional.ofNullable(employee)
.map(Employee::getAddress)
.map(Address::getCity)
.map(City::toString)
.orElse(null);
Lambda trick: first non-null object
● Commons-lang: ObjectUtils.firstNonNull
<T> T firstNonNull(T... values)
● Fine if values are cheap to provide
firstNonNull(
customer.getCart().getRecommendations(),
getRecommendationsFor(customer.history()),
getBestSellers());
Lambda trick: first non-null object
Recommendations recommendations = firstNonNull(
customer.getCart()::getRecommendations,
() -> getRecommendationsFor(customer.history()),
this::getBestSellers);
● Use of suppliers can avoid work, or parallelize it.
public static <T> T firstNonNull(Supplier<T>... values) {
return Stream.of(values) // .parallel()
.map(Supplier::get)
.filter(Objects::nonNull)
.findFirst().orElse(null);
}
Lambda Trick: Multi-method interfaces
public interface FileVisitor {
FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs);
FileVisitResult visitFile(Path file, BasicFileAttributes attrs);
FileVisitResult visitFileFailed(Path file, IOException exc);
FileVisitResult postVisitDirectory(Path dir, IOException exc);
}
● Helper methods can create instances from one
or more lambdas
Lambda Trick: Multi-method interfaces
public static FileVisitor visitor(
BiFunction<Path, BasicFileAttributes, FileVisitResult> preVisitDirectory,
BiFunction<Path, BasicFileAttributes, FileVisitResult> visitFile,
BiFunction<Path, IOException, FileVisitResult> visitFileFailed,
BiFunction<Path, IOException, FileVisitResult> postVisitDirectory) {
return new FileVisitor<Path>() {
@Override public FileVisitResult preVisitDirectory(
Path dir, BasicFileAttributes attrs) throws IOException {
return preVisitDirectory.apply(dir, attrs);
}
….
};
}
Lambda Trick: Multi-method interfaces
public static FileVisitor fileVisitor(
BiConsumer<Path, BasicFileAttributes> visitFile) {
return new SimpleFileVisitor() {
@Override
public FileVisitResult visitFile(T file, BasicFileAttributes attrs) {
visitFile.accept(file, attrs);
return FileVisitResult.CONTINUE;
}
};
}
Exception Transparency
public void createFiles(List<File> files) throws IOException {
files.forEach(File::createNewFile);
}
Error:
incompatible thrown types java.io.IOException in method reference
● Exception transparency was discussed, but...
type theory.
Catching Exceptions within Lambda
public void createFiles(List<File> files) { // no throws...
files.forEach(file -> {
try {
file.createNewFile();
} catch (IOException e) {
throw new RuntimeException(e);
}
});
}
Exception Transparency via Generics
public interface EConsumer<T, E extends Throwable> {
void accept(T t) throws E;
}
public interface Iterable<T> { // Bizzaro Java
...
default <E extends Throwable> void forEach(
EConsumer<? super T, E> action) throws E { ... }
}
Exception Transparency via Generics
● Type inference actually works OK with this
– Provided you only have one throw type
● Signatures get messy
● Generally not worth it
“Uncheck” Exceptions
● Use jOOλ library (https://github.com/jOOQ/jOOL)
@FunctionalInterface public interface CheckedConsumer<T> {
void accept(T t) throws Throwable;
}
public static <T, R> Consumer<T, R> consumer(
CheckedConsumer<T, R> function) { … }
public void createFiles(List<File> files) { // no throws at all...
files.forEach(Unchecked.consumer(File::createNewFile));
}
Design Patterns
● Wikipedia: A general repeatable solution to a
commonly occurring problem
● Stuart Halloway: A code smell
– Design patterns tend to point to language
deficiencies
● Many patterns are of the form
boilerPlate customCode moreBoilerPlate
Resource management in Java 6
String result;
InputStream stream = openStream();
try {
result = process(stream);
}
finally {
stream.close();
}
Resource management In Java 7
String result;
try (InputStream stream = openStream()) {
result = process(stream);
}
But what if I forget?...
String result = process(openStream()); // resource leak!!!
Resource management In Java 7
try(Lock lock = acquireLock()) {
Account account = getAccount();
debit(account);
}
Try-with-resources only works for AutoClosable
Lock cannot be converted to AutoCloseable
Resource Management with Lambdas
public class AccountManager {
private Lock lock;
private Account account;
public <T> T workWithAccount(Consumer<Account> work) {
lock.lock();
try { work.accept(account); }
finally { lock.unlock(); }
}
}
accountManager.workWithAccount(account -> debit(account));
Laziness
● Lambda's are great for lazy evaluation
● Vavr (formerly javaslang) has a good Lazy
● Note – evaluation may well happen on a
different thread!
Using Lambda's for Type Safety
● Many APIs rely on String representations of
method names
– “Stringly typed”
– Refactoring tools are generally unaware of this
– Typos not caught at compile time
● Lambda expressions are often a good
alternative.
Make a comparator
● Creating a comparator: commons-beanutils
ComparatorChain comparator = new ComparatorChain(
new BeanComparator<>("lastName"));
comparator.addComparator(
new BeanComparator<>("firstName"));
@SuppressWarnings("unchecked")
Comparator<Person> personComparator = comparator;
Make a comparator
● Creating a comparator: better API
● Better – but still only stringly typed.
Comparator<Person> comparator = comparatorChain(
Person.class, "lastName", "firstName");
Make a comparator – type safety
● Creating a comparator: Java 8
Comparator<Person> comparator =
Comparator.comparing(Person::getLastName)
.thenComparing(Person::getFirstName);
JUnit 5 Parameterized Tests
public static Stream<Arguments> stringIntValues() {
return Stream.of(
Arguments.of("1", 1), Arguments.of("2", 2));
}
@ParameterizedTest
@MethodSource("stringIntValues")
public void testIntValueOf(String s, int i) {
assertEquals(s, String.valueOf(i));
}
JUnit 5 Type-safe Parameterized Tests
@TestFactory
Stream<DynamicTest> testIntValueOf() {
return Stream.of(tuple("1", 1), tuple("2", 2))
.map(tuple -> tuple.map((s, i) -> dynamicTest(
"testing " + i,
() -> assertEquals(s, String.valueOf(i)))));
}
JUnit 5 Type-safe Parameterized Tests
@TestFactory
Stream<DynamicTest> testIntValueOf() {
return parameterized(
(s, i) -> dynamicTest(
"testing " + i,
() -> assertEquals(s, String.valueOf(i))),
tuple("1", 1), tuple("2", 2));
}
@SafeVarargs
public static <T1, T2> Stream<DynamicTest> parameterized(
Function2<T1, T2, DynamicTest> test, Tuple2<T1, T2>... data) {
return Stream.of(data).map(datum -> datum.map(test));
}
Data driven tests - LambdataRunner
@RunWith(LambdataRunner.class)
public class StringTest {
@Test
public TestSpecs testSubString() {
return specs(
(s, start, end, expected) ->
assertEquals(expected, s.substring(start, end)),
datum("hello", 0, 5, "hello"),
datum("flexible", 1, 4, "lex"),
datum("hello", 5, 5, ""));
}
}
Best practices
● Prefer multiple single-method interfaces to
larger interfaces
– Barring that, consider factory methods taking in
labmdas
Best practices
● Use standard java.util.function classes where
applicable, or corresponding org.jooq.lambda
classes if Exception transparency is an issue.
Best practices
● Avoid overloading method names to accept
different lambdas of the same “shape”.
● Forces clients to cast their lambdas
public void doWork(Runnable work) { ... }
public void doWork(CheckedRunnable work) { ... }
Thank you!
http://www.slideshare.net/nainostrebor/
Please fill out the session survey!

More Related Content

What's hot

Sailing with Java 8 Streams
Sailing with Java 8 StreamsSailing with Java 8 Streams
Sailing with Java 8 Streams
Ganesh Samarthyam
 
Advanced Debugging Using Java Bytecodes
Advanced Debugging Using Java BytecodesAdvanced Debugging Using Java Bytecodes
Advanced Debugging Using Java Bytecodes
Ganesh Samarthyam
 
Inside the JVM - Follow the white rabbit!
Inside the JVM - Follow the white rabbit!Inside the JVM - Follow the white rabbit!
Inside the JVM - Follow the white rabbit!
Sylvain Wallez
 
Streams in Java 8
Streams in Java 8Streams in Java 8
Streams in Java 8
Tobias Coetzee
 
Building native Android applications with Mirah and Pindah
Building native Android applications with Mirah and PindahBuilding native Android applications with Mirah and Pindah
Building native Android applications with Mirah and Pindah
Nick Plante
 
Core Java - Quiz Questions - Bug Hunt
Core Java - Quiz Questions - Bug HuntCore Java - Quiz Questions - Bug Hunt
Core Java - Quiz Questions - Bug Hunt
CodeOps Technologies LLP
 
Extending C# with Roslyn and Code Aware Libraries
Extending C# with Roslyn and Code Aware LibrariesExtending C# with Roslyn and Code Aware Libraries
Extending C# with Roslyn and Code Aware Libraries
Carlo Pescio
 
The Kotlin Programming Language
The Kotlin Programming LanguageThe Kotlin Programming Language
The Kotlin Programming Language
intelliyole
 
Java Bytecode For Discriminating Developers - GeeCON 2011
Java Bytecode For Discriminating Developers - GeeCON 2011Java Bytecode For Discriminating Developers - GeeCON 2011
Java Bytecode For Discriminating Developers - GeeCON 2011
Anton Arhipov
 
Mastering Java Bytecode With ASM - 33rd degree, 2012
Mastering Java Bytecode With ASM - 33rd degree, 2012Mastering Java Bytecode With ASM - 33rd degree, 2012
Mastering Java Bytecode With ASM - 33rd degree, 2012
Anton Arhipov
 
Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2
José Paumard
 
Why Spring <3 Kotlin
Why Spring <3 KotlinWhy Spring <3 Kotlin
Why Spring <3 Kotlin
VMware Tanzu
 
OCJP Samples Questions: Exceptions and assertions
OCJP Samples Questions: Exceptions and assertionsOCJP Samples Questions: Exceptions and assertions
OCJP Samples Questions: Exceptions and assertions
Hari kiran G
 
The Sincerest Form of Flattery
The Sincerest Form of FlatteryThe Sincerest Form of Flattery
The Sincerest Form of Flattery
José Paumard
 
Java 5 and 6 New Features
Java 5 and 6 New FeaturesJava 5 and 6 New Features
Java 5 and 6 New Features
Jussi Pohjolainen
 
Kotlin: Challenges in JVM language design
Kotlin: Challenges in JVM language designKotlin: Challenges in JVM language design
Kotlin: Challenges in JVM language design
Andrey Breslav
 
모던자바의 역습
모던자바의 역습모던자바의 역습
모던자바의 역습
DoHyun Jung
 
Java Basics
Java BasicsJava Basics
Java Basics
Sunil OS
 
Lambda and Stream Master class - part 1
Lambda and Stream Master class - part 1Lambda and Stream Master class - part 1
Lambda and Stream Master class - part 1
José Paumard
 
Java Full Throttle
Java Full ThrottleJava Full Throttle
Java Full Throttle
José Paumard
 

What's hot (20)

Sailing with Java 8 Streams
Sailing with Java 8 StreamsSailing with Java 8 Streams
Sailing with Java 8 Streams
 
Advanced Debugging Using Java Bytecodes
Advanced Debugging Using Java BytecodesAdvanced Debugging Using Java Bytecodes
Advanced Debugging Using Java Bytecodes
 
Inside the JVM - Follow the white rabbit!
Inside the JVM - Follow the white rabbit!Inside the JVM - Follow the white rabbit!
Inside the JVM - Follow the white rabbit!
 
Streams in Java 8
Streams in Java 8Streams in Java 8
Streams in Java 8
 
Building native Android applications with Mirah and Pindah
Building native Android applications with Mirah and PindahBuilding native Android applications with Mirah and Pindah
Building native Android applications with Mirah and Pindah
 
Core Java - Quiz Questions - Bug Hunt
Core Java - Quiz Questions - Bug HuntCore Java - Quiz Questions - Bug Hunt
Core Java - Quiz Questions - Bug Hunt
 
Extending C# with Roslyn and Code Aware Libraries
Extending C# with Roslyn and Code Aware LibrariesExtending C# with Roslyn and Code Aware Libraries
Extending C# with Roslyn and Code Aware Libraries
 
The Kotlin Programming Language
The Kotlin Programming LanguageThe Kotlin Programming Language
The Kotlin Programming Language
 
Java Bytecode For Discriminating Developers - GeeCON 2011
Java Bytecode For Discriminating Developers - GeeCON 2011Java Bytecode For Discriminating Developers - GeeCON 2011
Java Bytecode For Discriminating Developers - GeeCON 2011
 
Mastering Java Bytecode With ASM - 33rd degree, 2012
Mastering Java Bytecode With ASM - 33rd degree, 2012Mastering Java Bytecode With ASM - 33rd degree, 2012
Mastering Java Bytecode With ASM - 33rd degree, 2012
 
Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2
 
Why Spring <3 Kotlin
Why Spring <3 KotlinWhy Spring <3 Kotlin
Why Spring <3 Kotlin
 
OCJP Samples Questions: Exceptions and assertions
OCJP Samples Questions: Exceptions and assertionsOCJP Samples Questions: Exceptions and assertions
OCJP Samples Questions: Exceptions and assertions
 
The Sincerest Form of Flattery
The Sincerest Form of FlatteryThe Sincerest Form of Flattery
The Sincerest Form of Flattery
 
Java 5 and 6 New Features
Java 5 and 6 New FeaturesJava 5 and 6 New Features
Java 5 and 6 New Features
 
Kotlin: Challenges in JVM language design
Kotlin: Challenges in JVM language designKotlin: Challenges in JVM language design
Kotlin: Challenges in JVM language design
 
모던자바의 역습
모던자바의 역습모던자바의 역습
모던자바의 역습
 
Java Basics
Java BasicsJava Basics
Java Basics
 
Lambda and Stream Master class - part 1
Lambda and Stream Master class - part 1Lambda and Stream Master class - part 1
Lambda and Stream Master class - part 1
 
Java Full Throttle
Java Full ThrottleJava Full Throttle
Java Full Throttle
 

Similar to Lambda Chops - Recipes for Simpler, More Expressive Code

Scala is java8.next()
Scala is java8.next()Scala is java8.next()
Scala is java8.next()
daewon jeong
 
Introduction to clojure
Introduction to clojureIntroduction to clojure
Introduction to clojure
Abbas Raza
 
Java 7 & 8 New Features
Java 7 & 8 New FeaturesJava 7 & 8 New Features
Java 7 & 8 New Features
Leandro Coutinho
 
Java 8 Feature Preview
Java 8 Feature PreviewJava 8 Feature Preview
Java 8 Feature Preview
Jim Bethancourt
 
Lambdas and Laughs
Lambdas and LaughsLambdas and Laughs
Lambdas and Laughs
Jim Bethancourt
 
Java 8 Workshop
Java 8 WorkshopJava 8 Workshop
Java 8 Workshop
Mario Fusco
 
Java 8 presentation
Java 8 presentationJava 8 presentation
Java 8 presentation
Van Huong
 
NLJUG University Sessie: Java Reborn, Powered by Ordina
NLJUG University Sessie: Java Reborn, Powered by OrdinaNLJUG University Sessie: Java Reborn, Powered by Ordina
NLJUG University Sessie: Java Reborn, Powered by Ordina
Martijn Blankestijn
 
FP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyondFP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyond
Mario Fusco
 
Java 8
Java 8Java 8
Java 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional InterfacesJava 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional Interfaces
Ganesh Samarthyam
 
New Features in JDK 8
New Features in JDK 8New Features in JDK 8
New Features in JDK 8
Martin Toshev
 
Atlassian Groovy Plugins
Atlassian Groovy PluginsAtlassian Groovy Plugins
Atlassian Groovy Plugins
Paul King
 
Developing android apps with java 8
Developing android apps with java 8Developing android apps with java 8
Developing android apps with java 8
Jorge Castillo Pérez
 
Lazy Java
Lazy JavaLazy Java
Lazy Java
J On The Beach
 
Lazy java
Lazy javaLazy java
Lazy java
Mario Fusco
 
Lazy Java
Lazy JavaLazy Java
Lazy Java
Nicola Pedot
 
Mario Fusco - Lazy Java - Codemotion Milan 2018
Mario Fusco - Lazy Java - Codemotion Milan 2018Mario Fusco - Lazy Java - Codemotion Milan 2018
Mario Fusco - Lazy Java - Codemotion Milan 2018
Codemotion
 
Java gets a closure
Java gets a closureJava gets a closure
Java gets a closure
Tomasz Kowalczewski
 
PHP 8: Process & Fixing Insanity
PHP 8: Process & Fixing InsanityPHP 8: Process & Fixing Insanity
PHP 8: Process & Fixing Insanity
GeorgePeterBanyard
 

Similar to Lambda Chops - Recipes for Simpler, More Expressive Code (20)

Scala is java8.next()
Scala is java8.next()Scala is java8.next()
Scala is java8.next()
 
Introduction to clojure
Introduction to clojureIntroduction to clojure
Introduction to clojure
 
Java 7 & 8 New Features
Java 7 & 8 New FeaturesJava 7 & 8 New Features
Java 7 & 8 New Features
 
Java 8 Feature Preview
Java 8 Feature PreviewJava 8 Feature Preview
Java 8 Feature Preview
 
Lambdas and Laughs
Lambdas and LaughsLambdas and Laughs
Lambdas and Laughs
 
Java 8 Workshop
Java 8 WorkshopJava 8 Workshop
Java 8 Workshop
 
Java 8 presentation
Java 8 presentationJava 8 presentation
Java 8 presentation
 
NLJUG University Sessie: Java Reborn, Powered by Ordina
NLJUG University Sessie: Java Reborn, Powered by OrdinaNLJUG University Sessie: Java Reborn, Powered by Ordina
NLJUG University Sessie: Java Reborn, Powered by Ordina
 
FP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyondFP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyond
 
Java 8
Java 8Java 8
Java 8
 
Java 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional InterfacesJava 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional Interfaces
 
New Features in JDK 8
New Features in JDK 8New Features in JDK 8
New Features in JDK 8
 
Atlassian Groovy Plugins
Atlassian Groovy PluginsAtlassian Groovy Plugins
Atlassian Groovy Plugins
 
Developing android apps with java 8
Developing android apps with java 8Developing android apps with java 8
Developing android apps with java 8
 
Lazy Java
Lazy JavaLazy Java
Lazy Java
 
Lazy java
Lazy javaLazy java
Lazy java
 
Lazy Java
Lazy JavaLazy Java
Lazy Java
 
Mario Fusco - Lazy Java - Codemotion Milan 2018
Mario Fusco - Lazy Java - Codemotion Milan 2018Mario Fusco - Lazy Java - Codemotion Milan 2018
Mario Fusco - Lazy Java - Codemotion Milan 2018
 
Java gets a closure
Java gets a closureJava gets a closure
Java gets a closure
 
PHP 8: Process & Fixing Insanity
PHP 8: Process & Fixing InsanityPHP 8: Process & Fixing Insanity
PHP 8: Process & Fixing Insanity
 

Recently uploaded

GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
Neo4j
 
What is Augmented Reality Image Tracking
What is Augmented Reality Image TrackingWhat is Augmented Reality Image Tracking
What is Augmented Reality Image Tracking
pavan998932
 
Codeigniter VS Cakephp Which is Better for Web Development.pdf
Codeigniter VS Cakephp Which is Better for Web Development.pdfCodeigniter VS Cakephp Which is Better for Web Development.pdf
Codeigniter VS Cakephp Which is Better for Web Development.pdf
Semiosis Software Private Limited
 
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit ParisNeo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j
 
Mobile app Development Services | Drona Infotech
Mobile app Development Services  | Drona InfotechMobile app Development Services  | Drona Infotech
Mobile app Development Services | Drona Infotech
Drona Infotech
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
rickgrimesss22
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
Rakesh Kumar R
 
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket ManagementUtilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate
 
Graspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code AnalysisGraspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code Analysis
Aftab Hussain
 
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
kalichargn70th171
 
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
Google
 
Preparing Non - Technical Founders for Engaging a Tech Agency
Preparing Non - Technical Founders for Engaging  a  Tech AgencyPreparing Non - Technical Founders for Engaging  a  Tech Agency
Preparing Non - Technical Founders for Engaging a Tech Agency
ISH Technologies
 
Launch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in MinutesLaunch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in Minutes
Roshan Dwivedi
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
Fermin Galan
 
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI AppAI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
Google
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
Shane Coughlan
 
Energy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina JonuziEnergy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina Jonuzi
Green Software Development
 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
Deuglo Infosystem Pvt Ltd
 
Artificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension FunctionsArtificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension Functions
Octavian Nadolu
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOMLORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
lorraineandreiamcidl
 

Recently uploaded (20)

GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
 
What is Augmented Reality Image Tracking
What is Augmented Reality Image TrackingWhat is Augmented Reality Image Tracking
What is Augmented Reality Image Tracking
 
Codeigniter VS Cakephp Which is Better for Web Development.pdf
Codeigniter VS Cakephp Which is Better for Web Development.pdfCodeigniter VS Cakephp Which is Better for Web Development.pdf
Codeigniter VS Cakephp Which is Better for Web Development.pdf
 
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit ParisNeo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
 
Mobile app Development Services | Drona Infotech
Mobile app Development Services  | Drona InfotechMobile app Development Services  | Drona Infotech
Mobile app Development Services | Drona Infotech
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
 
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket ManagementUtilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
 
Graspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code AnalysisGraspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code Analysis
 
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
 
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
 
Preparing Non - Technical Founders for Engaging a Tech Agency
Preparing Non - Technical Founders for Engaging  a  Tech AgencyPreparing Non - Technical Founders for Engaging  a  Tech Agency
Preparing Non - Technical Founders for Engaging a Tech Agency
 
Launch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in MinutesLaunch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in Minutes
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
 
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI AppAI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
 
Energy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina JonuziEnergy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina Jonuzi
 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
 
Artificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension FunctionsArtificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension Functions
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOMLORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
 

Lambda Chops - Recipes for Simpler, More Expressive Code

  • 1. Ian Robertson Lambda Chops Recipes for Simpler, More Expressive Code
  • 2. Agenda ● Lambda review ● Lambda tricks ● Lack of exception transparency ● Turning patterns into libraries ● Adding type safety with lambdas ● API design best practices
  • 3. About Me ● Application Architect at Myriad Genetics ● 17 years experience of working on large-scale Java projects ● Twitter: @nainostrebor ● https://github.com/irobertson ● JavaOne Rockstar
  • 4. Disclaimer ● Not all code shown in this talk is optimally performant. ● Neither is it particularly non-performant. ● Most of the time, expressiveness trumps performance.
  • 5. Lambdas ● New in Java 8. ● More than just anon inner classes on steroids ● Represented by single method interface. Function<String, Integer> length = (String s) -> { return s.length(); }; …................................................ = s -> s.length(); …................................................ = String::length;
  • 6. Primary advertised use case: streams ● Much more expressive ● Multi-core friendly Map<City, Double> engineerSalaryByCity = employees.stream() .filter(e -> e.getJobType().equals("Engineer")) .collect(Collectors.groupingBy( Employee::getCity, Collectors.averagingDouble(Employee::getSalary)));
  • 7. Lambdas allow us to refer to an action without actually doing the action.
  • 8. Lambda trick: Null-Safe Navigation ● Groovy folks can write employee?.getAddress()?.getCity()?.toString() ● If anything along the way is null, returns null ● Java equivalent: (employee != null && employee.getAddress() != null && employee.getAddress().getCity() != null) ? employee.getAddress().getCity().toString() : null;
  • 9. Lambda trick: Null-Safe Navigation ● Alternative – (ab)use Optional String cityName = Optional.ofNullable(employee) .map(Employee::getAddress) .map(Address::getCity) .map(City::toString) .orElse(null);
  • 10. Lambda trick: first non-null object ● Commons-lang: ObjectUtils.firstNonNull <T> T firstNonNull(T... values) ● Fine if values are cheap to provide firstNonNull( customer.getCart().getRecommendations(), getRecommendationsFor(customer.history()), getBestSellers());
  • 11. Lambda trick: first non-null object Recommendations recommendations = firstNonNull( customer.getCart()::getRecommendations, () -> getRecommendationsFor(customer.history()), this::getBestSellers); ● Use of suppliers can avoid work, or parallelize it. public static <T> T firstNonNull(Supplier<T>... values) { return Stream.of(values) // .parallel() .map(Supplier::get) .filter(Objects::nonNull) .findFirst().orElse(null); }
  • 12. Lambda Trick: Multi-method interfaces public interface FileVisitor { FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs); FileVisitResult visitFile(Path file, BasicFileAttributes attrs); FileVisitResult visitFileFailed(Path file, IOException exc); FileVisitResult postVisitDirectory(Path dir, IOException exc); } ● Helper methods can create instances from one or more lambdas
  • 13. Lambda Trick: Multi-method interfaces public static FileVisitor visitor( BiFunction<Path, BasicFileAttributes, FileVisitResult> preVisitDirectory, BiFunction<Path, BasicFileAttributes, FileVisitResult> visitFile, BiFunction<Path, IOException, FileVisitResult> visitFileFailed, BiFunction<Path, IOException, FileVisitResult> postVisitDirectory) { return new FileVisitor<Path>() { @Override public FileVisitResult preVisitDirectory( Path dir, BasicFileAttributes attrs) throws IOException { return preVisitDirectory.apply(dir, attrs); } …. }; }
  • 14. Lambda Trick: Multi-method interfaces public static FileVisitor fileVisitor( BiConsumer<Path, BasicFileAttributes> visitFile) { return new SimpleFileVisitor() { @Override public FileVisitResult visitFile(T file, BasicFileAttributes attrs) { visitFile.accept(file, attrs); return FileVisitResult.CONTINUE; } }; }
  • 15. Exception Transparency public void createFiles(List<File> files) throws IOException { files.forEach(File::createNewFile); } Error: incompatible thrown types java.io.IOException in method reference ● Exception transparency was discussed, but... type theory.
  • 16. Catching Exceptions within Lambda public void createFiles(List<File> files) { // no throws... files.forEach(file -> { try { file.createNewFile(); } catch (IOException e) { throw new RuntimeException(e); } }); }
  • 17. Exception Transparency via Generics public interface EConsumer<T, E extends Throwable> { void accept(T t) throws E; } public interface Iterable<T> { // Bizzaro Java ... default <E extends Throwable> void forEach( EConsumer<? super T, E> action) throws E { ... } }
  • 18. Exception Transparency via Generics ● Type inference actually works OK with this – Provided you only have one throw type ● Signatures get messy ● Generally not worth it
  • 19. “Uncheck” Exceptions ● Use jOOλ library (https://github.com/jOOQ/jOOL) @FunctionalInterface public interface CheckedConsumer<T> { void accept(T t) throws Throwable; } public static <T, R> Consumer<T, R> consumer( CheckedConsumer<T, R> function) { … } public void createFiles(List<File> files) { // no throws at all... files.forEach(Unchecked.consumer(File::createNewFile)); }
  • 20. Design Patterns ● Wikipedia: A general repeatable solution to a commonly occurring problem ● Stuart Halloway: A code smell – Design patterns tend to point to language deficiencies ● Many patterns are of the form boilerPlate customCode moreBoilerPlate
  • 21. Resource management in Java 6 String result; InputStream stream = openStream(); try { result = process(stream); } finally { stream.close(); }
  • 22. Resource management In Java 7 String result; try (InputStream stream = openStream()) { result = process(stream); } But what if I forget?... String result = process(openStream()); // resource leak!!!
  • 23. Resource management In Java 7 try(Lock lock = acquireLock()) { Account account = getAccount(); debit(account); } Try-with-resources only works for AutoClosable Lock cannot be converted to AutoCloseable
  • 24. Resource Management with Lambdas public class AccountManager { private Lock lock; private Account account; public <T> T workWithAccount(Consumer<Account> work) { lock.lock(); try { work.accept(account); } finally { lock.unlock(); } } } accountManager.workWithAccount(account -> debit(account));
  • 25. Laziness ● Lambda's are great for lazy evaluation ● Vavr (formerly javaslang) has a good Lazy ● Note – evaluation may well happen on a different thread!
  • 26. Using Lambda's for Type Safety ● Many APIs rely on String representations of method names – “Stringly typed” – Refactoring tools are generally unaware of this – Typos not caught at compile time ● Lambda expressions are often a good alternative.
  • 27. Make a comparator ● Creating a comparator: commons-beanutils ComparatorChain comparator = new ComparatorChain( new BeanComparator<>("lastName")); comparator.addComparator( new BeanComparator<>("firstName")); @SuppressWarnings("unchecked") Comparator<Person> personComparator = comparator;
  • 28. Make a comparator ● Creating a comparator: better API ● Better – but still only stringly typed. Comparator<Person> comparator = comparatorChain( Person.class, "lastName", "firstName");
  • 29. Make a comparator – type safety ● Creating a comparator: Java 8 Comparator<Person> comparator = Comparator.comparing(Person::getLastName) .thenComparing(Person::getFirstName);
  • 30. JUnit 5 Parameterized Tests public static Stream<Arguments> stringIntValues() { return Stream.of( Arguments.of("1", 1), Arguments.of("2", 2)); } @ParameterizedTest @MethodSource("stringIntValues") public void testIntValueOf(String s, int i) { assertEquals(s, String.valueOf(i)); }
  • 31. JUnit 5 Type-safe Parameterized Tests @TestFactory Stream<DynamicTest> testIntValueOf() { return Stream.of(tuple("1", 1), tuple("2", 2)) .map(tuple -> tuple.map((s, i) -> dynamicTest( "testing " + i, () -> assertEquals(s, String.valueOf(i))))); }
  • 32. JUnit 5 Type-safe Parameterized Tests @TestFactory Stream<DynamicTest> testIntValueOf() { return parameterized( (s, i) -> dynamicTest( "testing " + i, () -> assertEquals(s, String.valueOf(i))), tuple("1", 1), tuple("2", 2)); } @SafeVarargs public static <T1, T2> Stream<DynamicTest> parameterized( Function2<T1, T2, DynamicTest> test, Tuple2<T1, T2>... data) { return Stream.of(data).map(datum -> datum.map(test)); }
  • 33. Data driven tests - LambdataRunner @RunWith(LambdataRunner.class) public class StringTest { @Test public TestSpecs testSubString() { return specs( (s, start, end, expected) -> assertEquals(expected, s.substring(start, end)), datum("hello", 0, 5, "hello"), datum("flexible", 1, 4, "lex"), datum("hello", 5, 5, "")); } }
  • 34. Best practices ● Prefer multiple single-method interfaces to larger interfaces – Barring that, consider factory methods taking in labmdas
  • 35. Best practices ● Use standard java.util.function classes where applicable, or corresponding org.jooq.lambda classes if Exception transparency is an issue.
  • 36. Best practices ● Avoid overloading method names to accept different lambdas of the same “shape”. ● Forces clients to cast their lambdas public void doWork(Runnable work) { ... } public void doWork(CheckedRunnable work) { ... }

Editor's Notes

  1. This is inversion of control