SlideShare a Scribd company logo
Java SE 8 Library Design
Using the new features well
Stephen Colebourne
Engineering Lead, OpenGamma
October 2016
Stephen Colebourne
● Java Champion, regular conference speaker
● Best known for date & time - Joda-Time and JSR-310
● More Joda projects - http://www.joda.org
● Major contributions in Apache Commons
● Blog - http://blog.joda.org
● Worked at OpenGamma for 6 years
Strata, from OpenGamma
● Open Source market risk library
● Valuation and risk calcs for finance
○ interest rate swap, FRA, CDS
● Great example of Java SE 8 coding style
http://strata.opengamma.io/
Introduction
⇒
Introduction
● Java SE 8 is a major update to Java
● Major new features
○ Lambdas
○ Streams
○ Methods on interfaces
○ Date and Time
Introduction
● Essential to rethink how you code
● Reconsider coding conventions
● Appreciate new design options
Agenda
● Lambdas
● Streams
● Design with Lambdas
● Abstraction
● Immutability
● Interfaces
● Optional
● Odds and Ends
Lambdas
λ
Lambdas
● Block of code
○ like an anonymous inner class
● Always assigned to a Functional Interface
○ an interface with one abstract method
○ Runnable, Callable, Comparator
● Uses target typing
○ context determines type of the lambda
// Java 7
List<Person> people = loadPeople();
Collections.sort(people, new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
return p1.name.compareTo(p2.name);
}
});
Lambdas
public interface Comparator<T> {
int compare(T obj1, T obj2);
}
// Java 7
Collections.sort(people, new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
return p1.name.compareTo(p2.name);
}
});
// Java 7
List<Person> people = loadPeople();
Collections.sort(people, new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
return p1.name.compareTo(p2.name);
}
});
Lambdas
public interface Comparator<T> {
int compare(T obj1, T obj2);
}
// Java 7
Collections.sort(people, new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
return p1.name.compareTo(p2.name);
}
});
// Java 7
List<Person> people = loadPeople();
Collections.sort(people, new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
return p1.name.compareTo(p2.name);
}
});
Lambdas
public interface Comparator<T> {
int compare(T obj1, T obj2);
}
// Java 8
people.sort((p1, p2) -> p1.name.compareTo(p2.name));
Top tips for Lambdas
● Use lambdas wherever appropriate
● Mostly, they just work
● Sometimes, the compiler needs a hint
○ use local variable
○ add the type to the lambda parameter
Lambdas
Lambdas affect code
but do they affect design?
Streams
♒
Streams
● Many loops have a similar "shape"
● Repetitive design patterns
● Stream library provides a way to abstract this
● Lambdas used to pass the interesting bits
Streams
List<Trade> trades = loadTrades();
List<Money> valued = new ArrayList<>();
for (Trade t : trades) {
if (t.isActive()) {
Money pv = t.presentValue();
valued.add(pv);
}
}
Streams
List<Trade> trades = loadTrades();
List<Money> valued = new ArrayList<>();
for (Trade t : trades) {
if (t.isActive()) {
Money pv = t.presentValue();
valued.add(pv);
}
}
Streams
List<Trade> trades = loadTrades();
List<Money> valued =
trades.stream()
.filter(t -> t.isActive())
.map(t -> t.presentValue())
.collect(Collectors.toList());
Streams
● New stream() method on Collection
● Sequence of operations on underlying data
● Logic passed in using a lambda
○ filter() to retain/remove
○ map() to change
○ reduce() to summarise
○ sorted() to sort using a comparator
Streams
trades.stream()
.filter(t -> t.isActive())
.map(t -> t.presentValue())
.collect(Collectors.toList());
Streams
trades.stream()
.filter(new Predicate<Trade>() {
public boolean test(Trade t) {
return t.isActive();
}
})
.map(new Function<Trade, Money>() {
public Money apply(Trade t) {
return t.presentValue();
}
})
.collect(Collectors.toList());
Streams
Stream API not practical
without lambdas
Exceptions in Streams
● For-each loop is a language feature
● Streams are implemented using regular methods
● Big difference in stack traces
Exceptions in Streams
java.lang.IllegalArgumentException: Oops
at com.opengamma.strata.calc.DefaultCalculationRunner.lambda$2(DefaultCalculationRunner.java:98)
at java.util.stream.ReferencePipeline$11$1.accept(ReferencePipeline.java:372)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.Iterator.forEachRemaining(Iterator.java:116)
at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at com.opengamma.strata.calc.DefaultCalculationRunner.calculate(DefaultCalculationRunner.java:100)
at com.opengamma.strata.calc.DefaultCalculationRunner.lambda$0(DefaultCalculationRunner.java:86)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.Iterator.forEachRemaining(Iterator.java:116)
at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at com.opengamma.strata.calc.DefaultCalculationRunner.calculate(DefaultCalculationRunner.java:87)
at com.opengamma.strata.calc.DefaultCalculationRunnerTest.calculate(DefaultCalculationRunnerTest.java:49)
Stack trace of
inner stream
Stack trace of
outer stream
Exceptions in Streams
java.lang.IllegalArgumentException: Oops
at com.opengamma.strata.calc.DefaultCalculationRunner.calculate(DefaultCalculationRunner.java:102)
at com.opengamma.strata.calc.DefaultCalculationRunner.calculate(DefaultCalculationRunner.java:87)
at com.opengamma.strata.calc.DefaultCalculationRunnerTest.calculate(DefaultCalculationRunnerTest.java:49)
Stack trace of
for-each loop
Top tips for streams
● Stream not always more readable than loop
● Stream exceptions can be much worse
● My advice:
○ use streams for small, localized, pieces of logic
○ be cautious using streams for large scale logic
● Strata uses for-each loops at top level
○ solely for shorter stack traces
Design with Lambdas
Design with Lambdas
● Lambda is converted to a functional interface
● Normal interface with one abstract method
● Java SE 8 adds many new functional interfaces
○ Function<T, R>
○ Predicate<T>
○ Supplier<T>
○ Consumer<T>
○ see java.util.function package
● Primitive versions only for long, int, double
Functional interfaces
● Learn the standard functional interfaces
● Only create new ones if adding additional value
○ lots of parameters
○ mix of primitive and object parameters
○ feature really needs a good name or Javadoc
Functional interface example
// API functional interface
@FunctionalInterface
public interface Perturbation {
public abstract double perturb(int index, double value);
}
// API method that can be used by a lambda
public Curve perturbed(Perturbation perturbation) { … }
// caller code
curve = curve.perturbed((i, v) -> v + 1e-4);
Functional interface example
// API functional interface
@FunctionalInterface
public interface Perturbation {
public abstract double perturb(int index, double value);
}
// API method that can be used by a lambda
public Curve perturbed(Perturbation perturbation) { … }
// caller code
curve = curve.perturbed((i, v) -> v + 1e-4);
Name has meaning
Method signature is complex
Time-series example
● A time-series stores changes to a value over time
● Date-based one like Map<LocalDate, Double>
● What if you want to change the values?
Time-series example
// API method that can be used by a lambda
public LocalDateDoubleTimeSeries
mapValues(DoubleUnaryOperator mapper){ … }
// caller code
ts = ts.mapValues(v -> v * 2);
Time-series example
// API method that can be used by a lambda
public LocalDateDoubleTimeSeries
mapValues(DoubleUnaryOperator mapper){ … }
// caller code
ts = ts.mapValues(v -> v * 2);
Multiplication - no need for
multipliedBy(double)
on the API
Time-series example
// API method that can be used by a lambda
public LocalDateDoubleTimeSeries
mapValues(DoubleUnaryOperator mapper){ … }
// caller code
ts = ts.mapValues(v -> v * 2);
ts = ts.mapValues(v -> v / 4);
Multiplication - no need for
multipliedBy(double)
on the API
Division - no need for
dividedBy(double)
on the API
Design with Lambdas
Method taking a lambda
can be more flexible design
Abstraction with Lambdas
✯
Abstraction
● Two or more classes with the same methods
● Abstract using an interface?
● Lambdas provide an alternative
● Consider an example with static methods
○ no way to abstract that with interfaces...
Abstraction
// standard API producing results
public static Money pv(FraTrade trade, Market md) { … }
public static Sens pv01(FraTrade trade, Market md) { … }
public static Double par(FraTrade trade, Market md) { … }
Abstraction
// standard API producing results
public static Money pv(FraTrade trade, Market md) { … }
public static Sens pv01(FraTrade trade, Market md) { … }
public static Double par(FraTrade trade, Market md) { … }
// functional interface matching all three methods
interface Calc<T> {
public abstract T invoke(FraTrade trade, Market market);
}
Abstraction
// create abstraction to access method by "measure" key
Map<Measure, Calc> CALCS = ImmutableMap.builder()
.put(Measures.PRESENT_VALUE, FraCalcs::pv)
.put(Measures.PV01, FraCalcs::pv01)
.put(Measures.PAR_RATE, FraCalcs:: par)
.build();
// can now invoke using measure
return CALCS.get(measure).invoke(trade, market);
Abstraction
● Class being abstracted was not changed
● Provides way to abstract over code you do not own
● Less need for reflection
Design with Lambdas
Lambdas can abstract
in dynamic/flexible ways
Immutability
Multi-threaded
● JDK provides many tools for concurrency
● Parallel streams makes it even easier
● But parallel code is not simple to get right
Thread problems
● What if trade modified by some other piece of code?
● Check-then-act bug
List<Trade> trades = loadTrades();
List<Money> valued =
trades.stream()
.filter(t -> t.isActive())
.map(t -> presentValue(t))
.collect(Collectors.toList());
Check
then Act
Immutable
● Threading bugs due to shared mutable state
● One solution is to use immutable beans
● No possibility of check-then-act type bug
Immutable beans
● Class should be final
○ no subclasses
● Fields must be final
○ needed for Java Memory Model
● Field types should be immutable
○ eg. don't use java.util.Date
● Factory methods and Builders instead of constructors
Immutable beans
● IDEs help you write mutable beans
● Need better tooling for immutable beans
○ AutoValue
○ Immutables.org
○ Joda-Beans
● Strata uses Joda-Beans
http://www.joda.org/joda-beans
Joda-Beans
@BeanDefinition
public final TradeInfo implements ImmutableBean {
/** The trade identifier. */
@PropertyDefinition(validate = "notNull")
private final StandardId tradeId;
/** The trade date. */
@PropertyDefinition(validate = "notNull")
private final LocalDate tradeDate;
}
Joda-Beans
● Source code generated for
○ getters
○ builder
○ equals/hashCode/toString
○ properties - like C#
● Can add your own code to the class and still regenerate
● Built in XML, JSON and Binary serialization
Immutable beans
● Most systems better using immutability everywhere
● Java SE 8 parallelStream() pushes at this
● Threading issues mostly eliminated
● No class hierarchies, use interfaces
Use interfaces
Trade
ProductTrade ResolvableTrade
SwapTrade FraTrade
Resolved
SwapTrade
Resolved
FraTrade
Use interfaces
● Concrete classes with no hierarchies
● Interfaces provide the hierarchy
● Methods on interfaces make this practical
● All implementations of interface should be immutable
○ "Implementations must be immutable and thread-safe beans."
● Strata uses immutable beans everywhere
Immutability
It is time to move on
from mutable data objects
Interfaces
I
Interfaces
● Two changes to interfaces
● Default methods
○ normal method, but on an interface
○ cannot default equals/hashCode/toString
● Static methods
○ normal static method, but on an interface
Coding Style
● Use modifiers in interfaces
● Much clearer now there are different types of method
● Prepares for private methods in Java SE 9
public interface Foo {
public static of(String id) { … }
public abstract isEmpty();
public default isNotEmpty() { … }
}
Interfaces
● Methods on interfaces changes design
● Interfaces are part of macro-design
○ lambdas and streams affect micro-design
● Strata uses default and static methods liberally
Holiday Calendar
● Strata interface to specify which days are holidays
public interface HolidayCalendar {
// a normal abstract interface method
public abstract isHoliday(LocalDate date);
…
}
Holiday Calendar
● Default methods make the interface more useful
public interface HolidayCalendar {
public abstract isHoliday(LocalDate date);
// check if date is a business day
public default isBusinessDay(LocalDate date) {
return !isHoliday(date);
}
}
Holiday Calendar
● Default methods make the interface more useful
public interface HolidayCalendar {
public abstract isHoliday(LocalDate date);
// find the next business day
public default next(LocalDate date) {
LocalDate nextDay = date.plusDays(1);
return isHoliday(nextDay) ? next(nextDay) : nextDay;
}
}
Holiday Calendar
● Static methods avoid HolidayCalendarFactory
public interface HolidayCalendar {
// find holiday calendar by identifier such as DKCO
public static of(String id) {
// lookup calendar
}
}
Holiday Calendar
● Interface used just as would be expected
// find holiday calendar by identifier such as DKCO
HolidayCalendar cal = HolidayCalendar.of("DKCO");
// use calendar to select the trade start date
LocalDate startDate = cal.next(tradeDate);
Interfaces
● Interface now acts as abstract class
○ Only need abstract class if need abstracted state
○ but abstracted state is generally a bad idea
● Interface can now acts as a factory
○ Not suitable for all factory use cases*
* In Strata, holiday calendars are not really fixed at startup, but it made a good example for this talk!
Package-scoped implementation
● Can the interface be the only public API?
● Can the implementation class be package-scoped?
● Strata uses this pattern a lot
Interfaces
Consider package-scoped
factory and implementation
Optional and null
?
Optional and null
● New class Optional added to Java 8
● Opinions are polarized
○ some think it is the saviour of the universe
○ others think it is useless
● Used pragmatically, can be very useful
Optional and null
● Simple concept - two states
○ present, with a value - Optional.of(foo)
○ empty - Optional.empty()
Optional and null
● Standard code using null
// library, returns null if not found
public Foo getValue(String key) { … }
// application code must remember to check for null
Foo foo = getValue(key);
if (foo == null) {
foo = Foo.DEFAULT; // or throw an exception
}
Optional and null
● Standard code using Optional
// library, returns Optional if not found
public Optional<Foo> findValue(String key) { … }
// application code
Foo foo = findValue(key).orElse(Foo.DEFAULT);
// or
Foo foo = findValue(key).orElseThrow( … );
Optional and null
● Important that a variable of type Optional is never null
● Prefer methods like map() and orElse()
● Minimise use of isPresent()
Optional
● Strata often uses set of 3-methods
public abstract Optional<T> findValue(DataId<T> id);
public default boolean containsValue(DataId<T> id) {
return findValue(id).isPresent();
}
public default T getValue(DataId<T> id) {
return findValue(id).orElseThrow(
() -> new MarketDataException());
}
Optional
● Optional is a class
● Some memory/performance cost to using it
● Not serializable
● Not ideal to be an instance variable
● JDK authors added it for return types
● Use in parameters often annoying for callers
● Use as return type gets best value from concept
http://blog.joda.org/2015/08/java-se-8-optional-pragmatic-approach.html
Optional in Strata
● Strata has no exposed nulls
● No part of the API will return null
● Optional used when something is optional
● Pragmatically, null is used within classes
Optional
Use Optional in a
pragmatic way
Odds and Ends
Java SE 8 version
● Use Java SE 8 update 40 or later
○ preferably use the latest available
● Earlier versions have annoying lambda/javac issues
Internal JDK packages
● Java SE 9 will remove access to some JDK packages
○ sun.*
○ com.sun.*
○ com.oracle.*
● Now is the time to prepare for this
○ Avoid sun.misc.Unsafe
○ Stick to the standard JDK API
Parameters
● Java SE 8 can reflect on parameter names
● Avoids need for additional libraries like paranamer
● Not enabled by default, must choose to include data
Checked exceptions
● Checked exceptions can be made to disappear
● Helper methods can convert to runtime exceptions
Unchecked.wrap(() -> {
// any code that might throw a checked exception
// converted to a runtime exception
});
Summary
J8
Summary
● Lots of good stuff in Java SE 8
● Design and coding standards change
● Lots more potential to abstract, but don't over-use
● Methods on interfaces add a lot of power
Key Strata design features
● Immutable data objects, using Joda-Beans
● Static methods on interfaces, package-scope impls
● Make use of new abstractions
● Beware stack traces with streams
● Pragmatic use of Optional, null never returned from API
Work in Finance?
● Take a look at OpenGamma Strata
○ developed from the ground up in Java 8
○ lots of good Java 8 techniques and utilities
● High quality library for market risk
○ day counts, schedules, holidays, indices
○ models and pricing for swaps, FRAs, swaptions, FX, futures…
○ open source and stable release v1.1
http://strata.opengamma.io/

More Related Content

PDF
Java SE 8 best practices
PPTX
55 New Features in Java SE 8
PDF
Functional Java 8 - Introduction
PDF
Java 8 features
ODP
Introduction to Java 8
PDF
Java SE 8
PPTX
Java 8 Features
Java SE 8 best practices
55 New Features in Java SE 8
Functional Java 8 - Introduction
Java 8 features
Introduction to Java 8
Java SE 8
Java 8 Features

What's hot (20)

PPTX
Java 8 Features
PPTX
New Features in JDK 8
PPTX
Introduction of Java 8 with emphasis on Lambda Expressions and Streams
PPTX
Whats New in Java 5, 6, & 7 (Webinar Presentation - June 2013)
PPTX
Improved Developer Productivity In JDK8
PPTX
Java 8 Feature Preview
PPTX
Java SE 8 - New Features
PDF
Code generating beans in Java
PPTX
JDK8 Lambdas and Streams: Changing The Way You Think When Developing Java
PDF
New Features Of JDK 7
PPTX
Lambdas : Beyond The Basics
PDF
Java 8 ​and ​Best Practices
PPTX
10 Sets of Best Practices for Java 8
PPTX
java 8 new features
PDF
Java 8 features
PPTX
Java 8 Lambda and Streams
PDF
Lambdas and Streams in Java SE 8: Making Bulk Operations simple - Simon Ritter
PPTX
Project Jigsaw in JDK9
PDF
Java 8 Lambda Expressions & Streams
PDF
Java 8 by example!
Java 8 Features
New Features in JDK 8
Introduction of Java 8 with emphasis on Lambda Expressions and Streams
Whats New in Java 5, 6, & 7 (Webinar Presentation - June 2013)
Improved Developer Productivity In JDK8
Java 8 Feature Preview
Java SE 8 - New Features
Code generating beans in Java
JDK8 Lambdas and Streams: Changing The Way You Think When Developing Java
New Features Of JDK 7
Lambdas : Beyond The Basics
Java 8 ​and ​Best Practices
10 Sets of Best Practices for Java 8
java 8 new features
Java 8 features
Java 8 Lambda and Streams
Lambdas and Streams in Java SE 8: Making Bulk Operations simple - Simon Ritter
Project Jigsaw in JDK9
Java 8 Lambda Expressions & Streams
Java 8 by example!
Ad

Viewers also liked (20)

PDF
Code Review Matters and Manners
PDF
[Suriano & Perry] [Library Design: Community Transformation] IFLA LBES 2016
PDF
Public Library Design
PPTX
Peckham Library Case Study
PPTX
ARCHITECTURAL STANDARDS
PDF
Library Design and Architecture - 2012
PPTX
Is Groovy better for testing than Java?
PPTX
Hanna Springs Sculpture Garden
PPTX
Forrest Dweller Sculpture Garden
PPTX
Space Solutions in Makerspaces at Darien Library
PPT
PAARL Standards for Academic Libraries 2010 (Final Draft Proposal)
PPTX
Presentation by IPS Yale Center for British Art 2014 Fellow Alice Insley
PPT
Library Design for the 21st Century Learner: CEFPI Southern Region
PPT
Raskar 6Sight Keynote Talk Nov09
DOC
Java library synopsis
PPTX
Developer Friendly API Design
PPTX
The beginning of visual art and design
PPT
Visual Arts on Blackboard
PPTX
Re-implementing Thrift using MDE
PPT
Library Newbuild - trends in academic library design
Code Review Matters and Manners
[Suriano & Perry] [Library Design: Community Transformation] IFLA LBES 2016
Public Library Design
Peckham Library Case Study
ARCHITECTURAL STANDARDS
Library Design and Architecture - 2012
Is Groovy better for testing than Java?
Hanna Springs Sculpture Garden
Forrest Dweller Sculpture Garden
Space Solutions in Makerspaces at Darien Library
PAARL Standards for Academic Libraries 2010 (Final Draft Proposal)
Presentation by IPS Yale Center for British Art 2014 Fellow Alice Insley
Library Design for the 21st Century Learner: CEFPI Southern Region
Raskar 6Sight Keynote Talk Nov09
Java library synopsis
Developer Friendly API Design
The beginning of visual art and design
Visual Arts on Blackboard
Re-implementing Thrift using MDE
Library Newbuild - trends in academic library design
Ad

Similar to Java SE 8 library design (20)

PPTX
New features in jdk8 iti
PDF
PPTX
Java 8 presentation
PPTX
PPTX
Week-1..................................
ODP
Lambda Chops - Recipes for Simpler, More Expressive Code
PDF
Lambda Functions in Java 8
PPTX
Intro to java 8
PPTX
Java8 training - Class 1
PPTX
Java 8 new features
PDF
Java 8
PPTX
Lambdas and-streams-s ritter-v3
PPTX
What's New in Java 8
PDF
Apouc 2014-java-8-create-the-future
PPTX
Functional Programming With Lambdas and Streams in JDK8
PPTX
java150929145120-lva1-app6892 (2).pptx
PDF
Java 8 best practices - Stephen Colebourne
PDF
javase8bestpractices-151015135520-lva1-app6892
PPTX
PPTX
Project Lambda: Evolution of Java
New features in jdk8 iti
Java 8 presentation
Week-1..................................
Lambda Chops - Recipes for Simpler, More Expressive Code
Lambda Functions in Java 8
Intro to java 8
Java8 training - Class 1
Java 8 new features
Java 8
Lambdas and-streams-s ritter-v3
What's New in Java 8
Apouc 2014-java-8-create-the-future
Functional Programming With Lambdas and Streams in JDK8
java150929145120-lva1-app6892 (2).pptx
Java 8 best practices - Stephen Colebourne
javase8bestpractices-151015135520-lva1-app6892
Project Lambda: Evolution of Java

Recently uploaded (20)

PDF
Wondershare Filmora 15 Crack With Activation Key [2025
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PPTX
Operating system designcfffgfgggggggvggggggggg
PPTX
Advanced SystemCare Ultimate Crack + Portable (2025)
PDF
AutoCAD Professional Crack 2025 With License Key
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PPTX
Monitoring Stack: Grafana, Loki & Promtail
PDF
Odoo Companies in India – Driving Business Transformation.pdf
PPTX
assetexplorer- product-overview - presentation
PPTX
Embracing Complexity in Serverless! GOTO Serverless Bengaluru
PDF
Complete Guide to Website Development in Malaysia for SMEs
PPTX
Oracle Fusion HCM Cloud Demo for Beginners
PDF
Designing Intelligence for the Shop Floor.pdf
PDF
iTop VPN 6.5.0 Crack + License Key 2025 (Premium Version)
PDF
Design an Analysis of Algorithms II-SECS-1021-03
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PDF
Salesforce Agentforce AI Implementation.pdf
PDF
Tally Prime Crack Download New Version 5.1 [2025] (License Key Free
PPTX
Transform Your Business with a Software ERP System
Wondershare Filmora 15 Crack With Activation Key [2025
Internet Downloader Manager (IDM) Crack 6.42 Build 41
Operating system designcfffgfgggggggvggggggggg
Advanced SystemCare Ultimate Crack + Portable (2025)
AutoCAD Professional Crack 2025 With License Key
Design an Analysis of Algorithms I-SECS-1021-03
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
Monitoring Stack: Grafana, Loki & Promtail
Odoo Companies in India – Driving Business Transformation.pdf
assetexplorer- product-overview - presentation
Embracing Complexity in Serverless! GOTO Serverless Bengaluru
Complete Guide to Website Development in Malaysia for SMEs
Oracle Fusion HCM Cloud Demo for Beginners
Designing Intelligence for the Shop Floor.pdf
iTop VPN 6.5.0 Crack + License Key 2025 (Premium Version)
Design an Analysis of Algorithms II-SECS-1021-03
Navsoft: AI-Powered Business Solutions & Custom Software Development
Salesforce Agentforce AI Implementation.pdf
Tally Prime Crack Download New Version 5.1 [2025] (License Key Free
Transform Your Business with a Software ERP System

Java SE 8 library design

  • 1. Java SE 8 Library Design Using the new features well Stephen Colebourne Engineering Lead, OpenGamma October 2016
  • 2. Stephen Colebourne ● Java Champion, regular conference speaker ● Best known for date & time - Joda-Time and JSR-310 ● More Joda projects - http://www.joda.org ● Major contributions in Apache Commons ● Blog - http://blog.joda.org ● Worked at OpenGamma for 6 years
  • 3. Strata, from OpenGamma ● Open Source market risk library ● Valuation and risk calcs for finance ○ interest rate swap, FRA, CDS ● Great example of Java SE 8 coding style http://strata.opengamma.io/
  • 5. Introduction ● Java SE 8 is a major update to Java ● Major new features ○ Lambdas ○ Streams ○ Methods on interfaces ○ Date and Time
  • 6. Introduction ● Essential to rethink how you code ● Reconsider coding conventions ● Appreciate new design options
  • 7. Agenda ● Lambdas ● Streams ● Design with Lambdas ● Abstraction ● Immutability ● Interfaces ● Optional ● Odds and Ends
  • 9. Lambdas ● Block of code ○ like an anonymous inner class ● Always assigned to a Functional Interface ○ an interface with one abstract method ○ Runnable, Callable, Comparator ● Uses target typing ○ context determines type of the lambda
  • 10. // Java 7 List<Person> people = loadPeople(); Collections.sort(people, new Comparator<Person>() { @Override public int compare(Person p1, Person p2) { return p1.name.compareTo(p2.name); } }); Lambdas public interface Comparator<T> { int compare(T obj1, T obj2); } // Java 7 Collections.sort(people, new Comparator<Person>() { @Override public int compare(Person p1, Person p2) { return p1.name.compareTo(p2.name); } });
  • 11. // Java 7 List<Person> people = loadPeople(); Collections.sort(people, new Comparator<Person>() { @Override public int compare(Person p1, Person p2) { return p1.name.compareTo(p2.name); } }); Lambdas public interface Comparator<T> { int compare(T obj1, T obj2); } // Java 7 Collections.sort(people, new Comparator<Person>() { @Override public int compare(Person p1, Person p2) { return p1.name.compareTo(p2.name); } });
  • 12. // Java 7 List<Person> people = loadPeople(); Collections.sort(people, new Comparator<Person>() { @Override public int compare(Person p1, Person p2) { return p1.name.compareTo(p2.name); } }); Lambdas public interface Comparator<T> { int compare(T obj1, T obj2); } // Java 8 people.sort((p1, p2) -> p1.name.compareTo(p2.name));
  • 13. Top tips for Lambdas ● Use lambdas wherever appropriate ● Mostly, they just work ● Sometimes, the compiler needs a hint ○ use local variable ○ add the type to the lambda parameter
  • 14. Lambdas Lambdas affect code but do they affect design?
  • 16. Streams ● Many loops have a similar "shape" ● Repetitive design patterns ● Stream library provides a way to abstract this ● Lambdas used to pass the interesting bits
  • 17. Streams List<Trade> trades = loadTrades(); List<Money> valued = new ArrayList<>(); for (Trade t : trades) { if (t.isActive()) { Money pv = t.presentValue(); valued.add(pv); } }
  • 18. Streams List<Trade> trades = loadTrades(); List<Money> valued = new ArrayList<>(); for (Trade t : trades) { if (t.isActive()) { Money pv = t.presentValue(); valued.add(pv); } }
  • 19. Streams List<Trade> trades = loadTrades(); List<Money> valued = trades.stream() .filter(t -> t.isActive()) .map(t -> t.presentValue()) .collect(Collectors.toList());
  • 20. Streams ● New stream() method on Collection ● Sequence of operations on underlying data ● Logic passed in using a lambda ○ filter() to retain/remove ○ map() to change ○ reduce() to summarise ○ sorted() to sort using a comparator
  • 21. Streams trades.stream() .filter(t -> t.isActive()) .map(t -> t.presentValue()) .collect(Collectors.toList());
  • 22. Streams trades.stream() .filter(new Predicate<Trade>() { public boolean test(Trade t) { return t.isActive(); } }) .map(new Function<Trade, Money>() { public Money apply(Trade t) { return t.presentValue(); } }) .collect(Collectors.toList());
  • 23. Streams Stream API not practical without lambdas
  • 24. Exceptions in Streams ● For-each loop is a language feature ● Streams are implemented using regular methods ● Big difference in stack traces
  • 25. Exceptions in Streams java.lang.IllegalArgumentException: Oops at com.opengamma.strata.calc.DefaultCalculationRunner.lambda$2(DefaultCalculationRunner.java:98) at java.util.stream.ReferencePipeline$11$1.accept(ReferencePipeline.java:372) at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) at java.util.Iterator.forEachRemaining(Iterator.java:116) at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499) at com.opengamma.strata.calc.DefaultCalculationRunner.calculate(DefaultCalculationRunner.java:100) at com.opengamma.strata.calc.DefaultCalculationRunner.lambda$0(DefaultCalculationRunner.java:86) at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) at java.util.Iterator.forEachRemaining(Iterator.java:116) at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499) at com.opengamma.strata.calc.DefaultCalculationRunner.calculate(DefaultCalculationRunner.java:87) at com.opengamma.strata.calc.DefaultCalculationRunnerTest.calculate(DefaultCalculationRunnerTest.java:49) Stack trace of inner stream Stack trace of outer stream
  • 26. Exceptions in Streams java.lang.IllegalArgumentException: Oops at com.opengamma.strata.calc.DefaultCalculationRunner.calculate(DefaultCalculationRunner.java:102) at com.opengamma.strata.calc.DefaultCalculationRunner.calculate(DefaultCalculationRunner.java:87) at com.opengamma.strata.calc.DefaultCalculationRunnerTest.calculate(DefaultCalculationRunnerTest.java:49) Stack trace of for-each loop
  • 27. Top tips for streams ● Stream not always more readable than loop ● Stream exceptions can be much worse ● My advice: ○ use streams for small, localized, pieces of logic ○ be cautious using streams for large scale logic ● Strata uses for-each loops at top level ○ solely for shorter stack traces
  • 29. Design with Lambdas ● Lambda is converted to a functional interface ● Normal interface with one abstract method ● Java SE 8 adds many new functional interfaces ○ Function<T, R> ○ Predicate<T> ○ Supplier<T> ○ Consumer<T> ○ see java.util.function package ● Primitive versions only for long, int, double
  • 30. Functional interfaces ● Learn the standard functional interfaces ● Only create new ones if adding additional value ○ lots of parameters ○ mix of primitive and object parameters ○ feature really needs a good name or Javadoc
  • 31. Functional interface example // API functional interface @FunctionalInterface public interface Perturbation { public abstract double perturb(int index, double value); } // API method that can be used by a lambda public Curve perturbed(Perturbation perturbation) { … } // caller code curve = curve.perturbed((i, v) -> v + 1e-4);
  • 32. Functional interface example // API functional interface @FunctionalInterface public interface Perturbation { public abstract double perturb(int index, double value); } // API method that can be used by a lambda public Curve perturbed(Perturbation perturbation) { … } // caller code curve = curve.perturbed((i, v) -> v + 1e-4); Name has meaning Method signature is complex
  • 33. Time-series example ● A time-series stores changes to a value over time ● Date-based one like Map<LocalDate, Double> ● What if you want to change the values?
  • 34. Time-series example // API method that can be used by a lambda public LocalDateDoubleTimeSeries mapValues(DoubleUnaryOperator mapper){ … } // caller code ts = ts.mapValues(v -> v * 2);
  • 35. Time-series example // API method that can be used by a lambda public LocalDateDoubleTimeSeries mapValues(DoubleUnaryOperator mapper){ … } // caller code ts = ts.mapValues(v -> v * 2); Multiplication - no need for multipliedBy(double) on the API
  • 36. Time-series example // API method that can be used by a lambda public LocalDateDoubleTimeSeries mapValues(DoubleUnaryOperator mapper){ … } // caller code ts = ts.mapValues(v -> v * 2); ts = ts.mapValues(v -> v / 4); Multiplication - no need for multipliedBy(double) on the API Division - no need for dividedBy(double) on the API
  • 37. Design with Lambdas Method taking a lambda can be more flexible design
  • 39. Abstraction ● Two or more classes with the same methods ● Abstract using an interface? ● Lambdas provide an alternative ● Consider an example with static methods ○ no way to abstract that with interfaces...
  • 40. Abstraction // standard API producing results public static Money pv(FraTrade trade, Market md) { … } public static Sens pv01(FraTrade trade, Market md) { … } public static Double par(FraTrade trade, Market md) { … }
  • 41. Abstraction // standard API producing results public static Money pv(FraTrade trade, Market md) { … } public static Sens pv01(FraTrade trade, Market md) { … } public static Double par(FraTrade trade, Market md) { … } // functional interface matching all three methods interface Calc<T> { public abstract T invoke(FraTrade trade, Market market); }
  • 42. Abstraction // create abstraction to access method by "measure" key Map<Measure, Calc> CALCS = ImmutableMap.builder() .put(Measures.PRESENT_VALUE, FraCalcs::pv) .put(Measures.PV01, FraCalcs::pv01) .put(Measures.PAR_RATE, FraCalcs:: par) .build(); // can now invoke using measure return CALCS.get(measure).invoke(trade, market);
  • 43. Abstraction ● Class being abstracted was not changed ● Provides way to abstract over code you do not own ● Less need for reflection
  • 44. Design with Lambdas Lambdas can abstract in dynamic/flexible ways
  • 46. Multi-threaded ● JDK provides many tools for concurrency ● Parallel streams makes it even easier ● But parallel code is not simple to get right
  • 47. Thread problems ● What if trade modified by some other piece of code? ● Check-then-act bug List<Trade> trades = loadTrades(); List<Money> valued = trades.stream() .filter(t -> t.isActive()) .map(t -> presentValue(t)) .collect(Collectors.toList()); Check then Act
  • 48. Immutable ● Threading bugs due to shared mutable state ● One solution is to use immutable beans ● No possibility of check-then-act type bug
  • 49. Immutable beans ● Class should be final ○ no subclasses ● Fields must be final ○ needed for Java Memory Model ● Field types should be immutable ○ eg. don't use java.util.Date ● Factory methods and Builders instead of constructors
  • 50. Immutable beans ● IDEs help you write mutable beans ● Need better tooling for immutable beans ○ AutoValue ○ Immutables.org ○ Joda-Beans ● Strata uses Joda-Beans http://www.joda.org/joda-beans
  • 51. Joda-Beans @BeanDefinition public final TradeInfo implements ImmutableBean { /** The trade identifier. */ @PropertyDefinition(validate = "notNull") private final StandardId tradeId; /** The trade date. */ @PropertyDefinition(validate = "notNull") private final LocalDate tradeDate; }
  • 52. Joda-Beans ● Source code generated for ○ getters ○ builder ○ equals/hashCode/toString ○ properties - like C# ● Can add your own code to the class and still regenerate ● Built in XML, JSON and Binary serialization
  • 53. Immutable beans ● Most systems better using immutability everywhere ● Java SE 8 parallelStream() pushes at this ● Threading issues mostly eliminated ● No class hierarchies, use interfaces
  • 54. Use interfaces Trade ProductTrade ResolvableTrade SwapTrade FraTrade Resolved SwapTrade Resolved FraTrade
  • 55. Use interfaces ● Concrete classes with no hierarchies ● Interfaces provide the hierarchy ● Methods on interfaces make this practical ● All implementations of interface should be immutable ○ "Implementations must be immutable and thread-safe beans." ● Strata uses immutable beans everywhere
  • 56. Immutability It is time to move on from mutable data objects
  • 58. Interfaces ● Two changes to interfaces ● Default methods ○ normal method, but on an interface ○ cannot default equals/hashCode/toString ● Static methods ○ normal static method, but on an interface
  • 59. Coding Style ● Use modifiers in interfaces ● Much clearer now there are different types of method ● Prepares for private methods in Java SE 9 public interface Foo { public static of(String id) { … } public abstract isEmpty(); public default isNotEmpty() { … } }
  • 60. Interfaces ● Methods on interfaces changes design ● Interfaces are part of macro-design ○ lambdas and streams affect micro-design ● Strata uses default and static methods liberally
  • 61. Holiday Calendar ● Strata interface to specify which days are holidays public interface HolidayCalendar { // a normal abstract interface method public abstract isHoliday(LocalDate date); … }
  • 62. Holiday Calendar ● Default methods make the interface more useful public interface HolidayCalendar { public abstract isHoliday(LocalDate date); // check if date is a business day public default isBusinessDay(LocalDate date) { return !isHoliday(date); } }
  • 63. Holiday Calendar ● Default methods make the interface more useful public interface HolidayCalendar { public abstract isHoliday(LocalDate date); // find the next business day public default next(LocalDate date) { LocalDate nextDay = date.plusDays(1); return isHoliday(nextDay) ? next(nextDay) : nextDay; } }
  • 64. Holiday Calendar ● Static methods avoid HolidayCalendarFactory public interface HolidayCalendar { // find holiday calendar by identifier such as DKCO public static of(String id) { // lookup calendar } }
  • 65. Holiday Calendar ● Interface used just as would be expected // find holiday calendar by identifier such as DKCO HolidayCalendar cal = HolidayCalendar.of("DKCO"); // use calendar to select the trade start date LocalDate startDate = cal.next(tradeDate);
  • 66. Interfaces ● Interface now acts as abstract class ○ Only need abstract class if need abstracted state ○ but abstracted state is generally a bad idea ● Interface can now acts as a factory ○ Not suitable for all factory use cases* * In Strata, holiday calendars are not really fixed at startup, but it made a good example for this talk!
  • 67. Package-scoped implementation ● Can the interface be the only public API? ● Can the implementation class be package-scoped? ● Strata uses this pattern a lot
  • 70. Optional and null ● New class Optional added to Java 8 ● Opinions are polarized ○ some think it is the saviour of the universe ○ others think it is useless ● Used pragmatically, can be very useful
  • 71. Optional and null ● Simple concept - two states ○ present, with a value - Optional.of(foo) ○ empty - Optional.empty()
  • 72. Optional and null ● Standard code using null // library, returns null if not found public Foo getValue(String key) { … } // application code must remember to check for null Foo foo = getValue(key); if (foo == null) { foo = Foo.DEFAULT; // or throw an exception }
  • 73. Optional and null ● Standard code using Optional // library, returns Optional if not found public Optional<Foo> findValue(String key) { … } // application code Foo foo = findValue(key).orElse(Foo.DEFAULT); // or Foo foo = findValue(key).orElseThrow( … );
  • 74. Optional and null ● Important that a variable of type Optional is never null ● Prefer methods like map() and orElse() ● Minimise use of isPresent()
  • 75. Optional ● Strata often uses set of 3-methods public abstract Optional<T> findValue(DataId<T> id); public default boolean containsValue(DataId<T> id) { return findValue(id).isPresent(); } public default T getValue(DataId<T> id) { return findValue(id).orElseThrow( () -> new MarketDataException()); }
  • 76. Optional ● Optional is a class ● Some memory/performance cost to using it ● Not serializable ● Not ideal to be an instance variable ● JDK authors added it for return types ● Use in parameters often annoying for callers ● Use as return type gets best value from concept http://blog.joda.org/2015/08/java-se-8-optional-pragmatic-approach.html
  • 77. Optional in Strata ● Strata has no exposed nulls ● No part of the API will return null ● Optional used when something is optional ● Pragmatically, null is used within classes
  • 78. Optional Use Optional in a pragmatic way
  • 80. Java SE 8 version ● Use Java SE 8 update 40 or later ○ preferably use the latest available ● Earlier versions have annoying lambda/javac issues
  • 81. Internal JDK packages ● Java SE 9 will remove access to some JDK packages ○ sun.* ○ com.sun.* ○ com.oracle.* ● Now is the time to prepare for this ○ Avoid sun.misc.Unsafe ○ Stick to the standard JDK API
  • 82. Parameters ● Java SE 8 can reflect on parameter names ● Avoids need for additional libraries like paranamer ● Not enabled by default, must choose to include data
  • 83. Checked exceptions ● Checked exceptions can be made to disappear ● Helper methods can convert to runtime exceptions Unchecked.wrap(() -> { // any code that might throw a checked exception // converted to a runtime exception });
  • 85. Summary ● Lots of good stuff in Java SE 8 ● Design and coding standards change ● Lots more potential to abstract, but don't over-use ● Methods on interfaces add a lot of power
  • 86. Key Strata design features ● Immutable data objects, using Joda-Beans ● Static methods on interfaces, package-scope impls ● Make use of new abstractions ● Beware stack traces with streams ● Pragmatic use of Optional, null never returned from API
  • 87. Work in Finance? ● Take a look at OpenGamma Strata ○ developed from the ground up in Java 8 ○ lots of good Java 8 techniques and utilities ● High quality library for market risk ○ day counts, schedules, holidays, indices ○ models and pricing for swaps, FRAs, swaptions, FX, futures… ○ open source and stable release v1.1 http://strata.opengamma.io/