SlideShare a Scribd company logo
Javaland 2015
Peter Lawrey
Legacy Lambda Code in Java
Agenda
• Lambdas: A complicated way to do something simple?
• Lambda Patterns we used.
• Lambda Patterns we shouldn’t have used.
• Lambda Patterns we have used since.
Counting elements in a Stream
long count = list.stream().count();
Counting elements in a Stream
long count = list.stream().count();
// Stream.count()
@Override
public final long count() {
return mapToLong(e -> 1L).sum();
}
Counting elements in a Stream
long count = list.stream().count();
// LongStream.sum()
@Override
public final long sum() {
// use better algorithm to compensate for
intermediate overflow?
return reduce(0, Long::sum);
}
Counting elements in a Stream
long count = list.parallelStream().count();
When the examples get more complex, lambdas become much
more interesting.
Porting a legacy C# application
For the last 8 months, Higher Frequency Trading ported a legacy
C# application with over 25K lines of code to Java.
We have translated many LINQ statements into Java 8 Stream +
Lambda.
What are some common patterns and anti-patterns we have
seen?
Summing BigDecimal
getResults().stream()
.reduce(BigDecimal.ZERO,
(bd, t) -> bd.add(t.getRequirement()),
BigDecimal::add);
Validate all entries
positions.stream().forEach(Position::validate);
Validate throws an exception.
Sorting by multiple fields.
setTrades(trades.stream()
.sorted(comparing(t -> t.getInfo().getDate())
.thenComparing(Position::getCUSIP)
.thenComparing(Position::getQuantity)
.reversed())
.collect(toList()));
Sorting by multiple fields,
Quantity reversed
setTrades(trades.stream()
.sorted(comparing(t -> t.getInfo().getDate())
.thenComparing(Position::getCUSIP)
.reversed()
.thenComparing(Position::getQuantity)
.reversed())
.collect(toList()));
Group By
Map<String, List<Position>> positionBySymbol =
positions.values().stream()
.filter(p -> p.getQuantity() != 0)
.collect(groupingBy(Position::getSymbol));
Streaming Maps
pos.entrySet().stream()
.filter(p -> p.getValue().getQuantity() != 0.0)
.forEach(p -> pos2.put(p.getKey(), p.getValue()));
Contains 2.0
if (list.stream()
.anyMatch(p -> p.getType() == Type.Cash)) {
Deep copy
List<Position> newPositions =
classPos.stream()
.map(Position::clone)
.collect(toList())
To collect or not to collect
(anti-pattern)
getTrades().stream()
.filter(t -> getDate().equals(t.getInfo().getDate()))
.collect(toList())
.forEach(t -> trades.add(t.getInfo()));
To collect or not to collect
(solution)
List<TradeInfo> trades =
getTrades().stream()
.filter(t -> getDate().equals(
t.getInfo().getDate()))
.map(Trade::getInfo)
.collect(toList());
Sort of sorted (anti-pattern)
Map<Date, List<Trade>> groupTrades = trades.stream()
.sorted(comparing(Trade::getDate))
.collect(groupingBy(Trade::getDate));
Sorting (solution)
Map<Date, List<Trade>> groupTrades = trades.stream()
.collect(groupingBy(
TradeDetail::getTradeDate,
TreeMap::new,
toList()));
Multi-sorted (anti-pattern)
return trade.stream()
.filter(t -> !isExcluded(t))
.sorted(comparing(Trade::getDate))
.sorted(comparing(Trade::getCUSIP))
.sorted(comparing(Trade::getNetAmount))
.collect(toList());
See slide 2 example for solution.
Concurrent removal
? anti-pattern ?
input.stream()
.filter(t -> t.getParent() == p.getParent())
.forEach(input::remove);
Optional Denial
Position todayPos = newPos.stream()
.filter(pos -> pos.getCUSIP()
.equals(p.getCUSIP()))
.findFirst().orElse(null);
if (todayPos != null) {
Optional Denial
Optional<MTrade> otodayTrade = trades.stream()
.filter(t -> t.getCUSIP().equals(p.getCUSIP()))
.findFirst();
MTrade todayTrade = null;
if (otodayTrade.isPresent()) todayTrade = otodayTrade.get();
if (todayTrade != null && todayTrade.getClosingPrice()!=null){
Optional for equals
public boolean equals(Object obj) {
return Optional.ofNullable(obj)
.filter(that -> that instanceof Test)
.map(that -> (Test)that)
.filter(that -> Objects.equals(this.s1, that.s1))
.filter(that -> Objects.equals(this.s2, that.s2))
.isPresent();
}
Posted by Marko Topolnik
Find the twenty most frequent words in a file
To use parallel or not?
List<String> words =
Files.lines(path).parallel()
.flatMap(line -> Arrays.asList(line.split("b")).stream())
.collect(groupingBy(w -> w, counting()))
.entrySet().stream()
.sorted(comparing(Map.Entry<String,Long>::getValue).reversed())
.limit(20)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
Lambdas and templates (before Java 8)
long value;
this.lock.lock();
try {
value = doSomething();
} finally {
this.lock.unlock();
}
Lambdas and templates (with Java 8)
public static <R> R with(Lock lock, Callable<R> work) {
lock.lock();
try {
return work.call();
} finally {
lock.unlock();
}
}
Lambdas and templates (with Java 8)
long value = with(lock, this::doSomething);
Note: with inlining, the temporary “Long” object can be eliminated.
Lambdas and performance
public void readMarshallable(Wire wire) {
wire.read(Fields.I).int32(x -> i = x)
.read(Fields.J).int32(x -> j = x)
.read(Fields.K).int32(x -> k = x)
.read(Fields.L).int32(x -> l = x)
.read(Fields.M).int32(x -> m = x)
.read(Fields.N).int32(x -> n = x)
.read(Fields.O).int32(x -> o = x)
.read(Fields.P).int32(x -> p = x);
}
Lambdas and performance
garbage in bytes per lambda
Lambdas and performance
-XX:BCEATraceLevel=3
Prints messages like
Skipping method because: code size (271) exceeds
MaxBCEAEstimateSize (150).
So I raised the
-XX:MaxBCEAEstimateSize=300
Lambda type inference
• Java 8 uses type inference much more than before.
• Inference can appear to be as a cast.
// error type is not known.
Object o = () -> System.out::println;
// type is inferred.
Runnable o = () -> System.out::println;
// type is inferred not cast at runtime.
Object o = (Runnable & Serializable)
() -> System.out::println;
Lambda internals
• Classes for Lambdas are generated at runtime.
lambda.getClass() still works.
• The contents of code in a lambda is added as a static method,
except …
• When a lambda expression refers to a method e.g.
this::method or Class::new no additional method is created.
• Provided your code is inlined, the lambda “object” can be
eliminated. This also works for anonymous inner classes.
End randomly (Don’t try this at home)
IntStream.range(0, 128).parallel()
.forEach(System::exit);
Q & A
http://vanillajava.blogspot.com/
Peter Lawrey
@PeterLawrey

More Related Content

PPT
Streams and lambdas the good, the bad and the ugly
PDF
JDD2014: Real life lambdas - Peter Lawrey
PDF
Modular Module Systems
ODP
Beginning Scala Svcc 2009
PDF
Advanced Tagless Final - Saying Farewell to Free
PPT
Functional programming with_scala
PDF
C Prog - Array
PDF
Делаем пользовательское Api на базе Shapeless
Streams and lambdas the good, the bad and the ugly
JDD2014: Real life lambdas - Peter Lawrey
Modular Module Systems
Beginning Scala Svcc 2009
Advanced Tagless Final - Saying Farewell to Free
Functional programming with_scala
C Prog - Array
Делаем пользовательское Api на базе Shapeless

What's hot (20)

PPT
Csc1100 lecture07 ch07_pt1-1
PDF
Cocoaheads Meetup / Alex Zimin / Swift magic
PPSX
C programming array & shorting
PDF
The Ring programming language version 1.3 book - Part 25 of 88
PDF
Generic Functional Programming with Type Classes
PDF
Scala collection methods flatMap and flatten are more powerful than monadic f...
PDF
Java8 stream
PDF
Pandas pythonfordatascience
PDF
Essence of the iterator pattern
KEY
Nu program language on Shibuya.lisp#5 LT
PPTX
Apache spark
PDF
The Ring programming language version 1.5.2 book - Part 21 of 181
PDF
Scala Higher Order Functions
PDF
Vim Registers
PDF
Simple IO Monad in 'Functional Programming in Scala'
PPTX
support vector regression
PDF
SupportVectorRegression
PPTX
multiple linear regression
PPTX
polynomial linear regression
PDF
Hive function-cheat-sheet
Csc1100 lecture07 ch07_pt1-1
Cocoaheads Meetup / Alex Zimin / Swift magic
C programming array & shorting
The Ring programming language version 1.3 book - Part 25 of 88
Generic Functional Programming with Type Classes
Scala collection methods flatMap and flatten are more powerful than monadic f...
Java8 stream
Pandas pythonfordatascience
Essence of the iterator pattern
Nu program language on Shibuya.lisp#5 LT
Apache spark
The Ring programming language version 1.5.2 book - Part 21 of 181
Scala Higher Order Functions
Vim Registers
Simple IO Monad in 'Functional Programming in Scala'
support vector regression
SupportVectorRegression
multiple linear regression
polynomial linear regression
Hive function-cheat-sheet
Ad

Viewers also liked (20)

PPTX
Deterministic behaviour and performance in trading systems
PPTX
Low latency for high throughput
PPTX
Responding rapidly when you have 100+ GB data sets in Java
PPTX
Determinism in finance
ODP
Low level java programming
PPTX
Low latency microservices in java QCon New York 2016
PPT
High Frequency Trading and NoSQL database
PPTX
Low latency in java 8 v5
PPTX
Microservices for performance - GOTO Chicago 2016
PPT
Introduction to OpenHFT for Melbourne Java Users Group
PPT
Reactive programming with examples
PDF
Stateless authentication for microservices applications - JavaLand 2015
PDF
NoSQL Riak MongoDB Elasticsearch - All The Same?
PPTX
JavaLand - Integration Testing How-to
PDF
Javaland keynote final
PPT
Advanced off heap ipc
PPTX
Cassandra Troubleshooting (for 2.0 and earlier)
PDF
Cassandra 3.0 advanced preview
PPT
Open HFT libraries in @Java
PPT
Thread Safe Interprocess Shared Memory in Java (in 7 mins)
Deterministic behaviour and performance in trading systems
Low latency for high throughput
Responding rapidly when you have 100+ GB data sets in Java
Determinism in finance
Low level java programming
Low latency microservices in java QCon New York 2016
High Frequency Trading and NoSQL database
Low latency in java 8 v5
Microservices for performance - GOTO Chicago 2016
Introduction to OpenHFT for Melbourne Java Users Group
Reactive programming with examples
Stateless authentication for microservices applications - JavaLand 2015
NoSQL Riak MongoDB Elasticsearch - All The Same?
JavaLand - Integration Testing How-to
Javaland keynote final
Advanced off heap ipc
Cassandra Troubleshooting (for 2.0 and earlier)
Cassandra 3.0 advanced preview
Open HFT libraries in @Java
Thread Safe Interprocess Shared Memory in Java (in 7 mins)
Ad

Similar to Legacy lambda code (20)

PDF
Big Data Analytics with Scala at SCALA.IO 2013
PPTX
Scala Back to Basics: Type Classes
PDF
Spark workshop
PPTX
Lambdas puzzler - Peter Lawrey
PPTX
Chapter 22. Lambda Expressions and LINQ
PDF
Practical cats
PPTX
Java gets a closure
PDF
No more struggles with Apache Spark workloads in production
PPTX
Java Foundations: Maps, Lambda and Stream API
PDF
Real Time Big Data Management
ODP
Stratosphere Intro (Java and Scala Interface)
PDF
Java 8
PPTX
Generics and Lambdas cocktail explained - Montreal JUG
PPTX
C++11 - A Change in Style - v2.0
PDF
Refactoring to Macros with Clojure
PDF
4 R Tutorial DPLYR Apply Function
PDF
Java 8 Stream API. A different way to process collections.
PDF
Scala in Places API
PPT
JBUG 11 - Scala For Java Programmers
PPTX
matlab presentation fro engninering students
Big Data Analytics with Scala at SCALA.IO 2013
Scala Back to Basics: Type Classes
Spark workshop
Lambdas puzzler - Peter Lawrey
Chapter 22. Lambda Expressions and LINQ
Practical cats
Java gets a closure
No more struggles with Apache Spark workloads in production
Java Foundations: Maps, Lambda and Stream API
Real Time Big Data Management
Stratosphere Intro (Java and Scala Interface)
Java 8
Generics and Lambdas cocktail explained - Montreal JUG
C++11 - A Change in Style - v2.0
Refactoring to Macros with Clojure
4 R Tutorial DPLYR Apply Function
Java 8 Stream API. A different way to process collections.
Scala in Places API
JBUG 11 - Scala For Java Programmers
matlab presentation fro engninering students

More from Peter Lawrey (6)

PPTX
Chronicle accelerate building a digital currency
PPTX
Chronicle Accelerate Crypto Investor conference
PPT
GC free coding in @Java presented @Geecon
PPT
Using BigDecimal and double
PPT
Introduction to chronicle (low latency persistence)
ODP
Writing and testing high frequency trading engines in java
Chronicle accelerate building a digital currency
Chronicle Accelerate Crypto Investor conference
GC free coding in @Java presented @Geecon
Using BigDecimal and double
Introduction to chronicle (low latency persistence)
Writing and testing high frequency trading engines in java

Recently uploaded (20)

PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
gpt5_lecture_notes_comprehensive_20250812015547.pdf
PDF
Spectral efficient network and resource selection model in 5G networks
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PDF
Electronic commerce courselecture one. Pdf
PPTX
A Presentation on Artificial Intelligence
PDF
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
PPTX
Machine Learning_overview_presentation.pptx
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
PDF
Empathic Computing: Creating Shared Understanding
PPT
Teaching material agriculture food technology
PPTX
Programs and apps: productivity, graphics, security and other tools
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
Approach and Philosophy of On baking technology
PDF
cuic standard and advanced reporting.pdf
PDF
Accuracy of neural networks in brain wave diagnosis of schizophrenia
PPTX
MYSQL Presentation for SQL database connectivity
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
Network Security Unit 5.pdf for BCA BBA.
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
gpt5_lecture_notes_comprehensive_20250812015547.pdf
Spectral efficient network and resource selection model in 5G networks
“AI and Expert System Decision Support & Business Intelligence Systems”
Electronic commerce courselecture one. Pdf
A Presentation on Artificial Intelligence
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
Machine Learning_overview_presentation.pptx
Mobile App Security Testing_ A Comprehensive Guide.pdf
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
Empathic Computing: Creating Shared Understanding
Teaching material agriculture food technology
Programs and apps: productivity, graphics, security and other tools
Digital-Transformation-Roadmap-for-Companies.pptx
Approach and Philosophy of On baking technology
cuic standard and advanced reporting.pdf
Accuracy of neural networks in brain wave diagnosis of schizophrenia
MYSQL Presentation for SQL database connectivity
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Network Security Unit 5.pdf for BCA BBA.

Legacy lambda code

  • 1. Javaland 2015 Peter Lawrey Legacy Lambda Code in Java
  • 2. Agenda • Lambdas: A complicated way to do something simple? • Lambda Patterns we used. • Lambda Patterns we shouldn’t have used. • Lambda Patterns we have used since.
  • 3. Counting elements in a Stream long count = list.stream().count();
  • 4. Counting elements in a Stream long count = list.stream().count(); // Stream.count() @Override public final long count() { return mapToLong(e -> 1L).sum(); }
  • 5. Counting elements in a Stream long count = list.stream().count(); // LongStream.sum() @Override public final long sum() { // use better algorithm to compensate for intermediate overflow? return reduce(0, Long::sum); }
  • 6. Counting elements in a Stream long count = list.parallelStream().count(); When the examples get more complex, lambdas become much more interesting.
  • 7. Porting a legacy C# application For the last 8 months, Higher Frequency Trading ported a legacy C# application with over 25K lines of code to Java. We have translated many LINQ statements into Java 8 Stream + Lambda. What are some common patterns and anti-patterns we have seen?
  • 8. Summing BigDecimal getResults().stream() .reduce(BigDecimal.ZERO, (bd, t) -> bd.add(t.getRequirement()), BigDecimal::add);
  • 10. Sorting by multiple fields. setTrades(trades.stream() .sorted(comparing(t -> t.getInfo().getDate()) .thenComparing(Position::getCUSIP) .thenComparing(Position::getQuantity) .reversed()) .collect(toList()));
  • 11. Sorting by multiple fields, Quantity reversed setTrades(trades.stream() .sorted(comparing(t -> t.getInfo().getDate()) .thenComparing(Position::getCUSIP) .reversed() .thenComparing(Position::getQuantity) .reversed()) .collect(toList()));
  • 12. Group By Map<String, List<Position>> positionBySymbol = positions.values().stream() .filter(p -> p.getQuantity() != 0) .collect(groupingBy(Position::getSymbol));
  • 13. Streaming Maps pos.entrySet().stream() .filter(p -> p.getValue().getQuantity() != 0.0) .forEach(p -> pos2.put(p.getKey(), p.getValue()));
  • 14. Contains 2.0 if (list.stream() .anyMatch(p -> p.getType() == Type.Cash)) {
  • 15. Deep copy List<Position> newPositions = classPos.stream() .map(Position::clone) .collect(toList())
  • 16. To collect or not to collect (anti-pattern) getTrades().stream() .filter(t -> getDate().equals(t.getInfo().getDate())) .collect(toList()) .forEach(t -> trades.add(t.getInfo()));
  • 17. To collect or not to collect (solution) List<TradeInfo> trades = getTrades().stream() .filter(t -> getDate().equals( t.getInfo().getDate())) .map(Trade::getInfo) .collect(toList());
  • 18. Sort of sorted (anti-pattern) Map<Date, List<Trade>> groupTrades = trades.stream() .sorted(comparing(Trade::getDate)) .collect(groupingBy(Trade::getDate));
  • 19. Sorting (solution) Map<Date, List<Trade>> groupTrades = trades.stream() .collect(groupingBy( TradeDetail::getTradeDate, TreeMap::new, toList()));
  • 20. Multi-sorted (anti-pattern) return trade.stream() .filter(t -> !isExcluded(t)) .sorted(comparing(Trade::getDate)) .sorted(comparing(Trade::getCUSIP)) .sorted(comparing(Trade::getNetAmount)) .collect(toList()); See slide 2 example for solution.
  • 21. Concurrent removal ? anti-pattern ? input.stream() .filter(t -> t.getParent() == p.getParent()) .forEach(input::remove);
  • 22. Optional Denial Position todayPos = newPos.stream() .filter(pos -> pos.getCUSIP() .equals(p.getCUSIP())) .findFirst().orElse(null); if (todayPos != null) {
  • 23. Optional Denial Optional<MTrade> otodayTrade = trades.stream() .filter(t -> t.getCUSIP().equals(p.getCUSIP())) .findFirst(); MTrade todayTrade = null; if (otodayTrade.isPresent()) todayTrade = otodayTrade.get(); if (todayTrade != null && todayTrade.getClosingPrice()!=null){
  • 24. Optional for equals public boolean equals(Object obj) { return Optional.ofNullable(obj) .filter(that -> that instanceof Test) .map(that -> (Test)that) .filter(that -> Objects.equals(this.s1, that.s1)) .filter(that -> Objects.equals(this.s2, that.s2)) .isPresent(); } Posted by Marko Topolnik
  • 25. Find the twenty most frequent words in a file To use parallel or not? List<String> words = Files.lines(path).parallel() .flatMap(line -> Arrays.asList(line.split("b")).stream()) .collect(groupingBy(w -> w, counting())) .entrySet().stream() .sorted(comparing(Map.Entry<String,Long>::getValue).reversed()) .limit(20) .map(Map.Entry::getKey) .collect(Collectors.toList());
  • 26. Lambdas and templates (before Java 8) long value; this.lock.lock(); try { value = doSomething(); } finally { this.lock.unlock(); }
  • 27. Lambdas and templates (with Java 8) public static <R> R with(Lock lock, Callable<R> work) { lock.lock(); try { return work.call(); } finally { lock.unlock(); } }
  • 28. Lambdas and templates (with Java 8) long value = with(lock, this::doSomething); Note: with inlining, the temporary “Long” object can be eliminated.
  • 29. Lambdas and performance public void readMarshallable(Wire wire) { wire.read(Fields.I).int32(x -> i = x) .read(Fields.J).int32(x -> j = x) .read(Fields.K).int32(x -> k = x) .read(Fields.L).int32(x -> l = x) .read(Fields.M).int32(x -> m = x) .read(Fields.N).int32(x -> n = x) .read(Fields.O).int32(x -> o = x) .read(Fields.P).int32(x -> p = x); }
  • 30. Lambdas and performance garbage in bytes per lambda
  • 31. Lambdas and performance -XX:BCEATraceLevel=3 Prints messages like Skipping method because: code size (271) exceeds MaxBCEAEstimateSize (150). So I raised the -XX:MaxBCEAEstimateSize=300
  • 32. Lambda type inference • Java 8 uses type inference much more than before. • Inference can appear to be as a cast. // error type is not known. Object o = () -> System.out::println; // type is inferred. Runnable o = () -> System.out::println; // type is inferred not cast at runtime. Object o = (Runnable & Serializable) () -> System.out::println;
  • 33. Lambda internals • Classes for Lambdas are generated at runtime. lambda.getClass() still works. • The contents of code in a lambda is added as a static method, except … • When a lambda expression refers to a method e.g. this::method or Class::new no additional method is created. • Provided your code is inlined, the lambda “object” can be eliminated. This also works for anonymous inner classes.
  • 34. End randomly (Don’t try this at home) IntStream.range(0, 128).parallel() .forEach(System::exit);