Date post: | 01-Dec-2014 |
Category: |
Technology |
Upload: | peter-lawrey |
View: | 573 times |
Download: | 2 times |
Streams and Lambdas – The Good, The Bad and the Ugly
Peter LawreyHigher Frequency Trading Ltd
Introduction
For the last 6 months, Higher Frequency Trading has been porting 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?
Contains 2.0
if (list.stream().anyMatch(p -> p.getType() == Type.Cash)) {
Deep Copy
List<Position> newPositions = classPos.stream()
.map(Position::clone)
.collect(toList())
Validate all entries
positions.forEach(Position::validate);
Validate throws an InvalidStateException if invalid
Summing BigDecimal
BigDecimal sum = getResults().stream()
.reduce(BigDecimal.ZERO,
(bd, t) -> bd.add(t.getRequirement()),
BigDecimal::add);
Sorting by multiple fields
setTrades(getTrades().stream()
.sorted(comparing(t -> t.getInfo().getDate())
.thenComparing(Position::getCUSIP)
.thenComparing(Position::getQuantity).reversed())
.collect(Collectors.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()));
To collect or not (anti-pattern)
getTrades().stream()
.filter(t -> getDate().equals(t.getInfo().getDate()))
.collect(toList())
.forEach(t -> trades.add(t.getInfo()));
To collect or not (solution)
List<Trade> trades = getTrades().stream()
.filter(t -> getDate().equals(t.getInfo().getDate()))
.map(t → t.getInfo())
.collect(Collectors.toList());
Sort of sorted (anti pattern)
Map<Date, List<Trade>> groupTrades =
trades.stream()
.sorted(comparing(Trade::getDate))
.collect(groupingBy(Trade::getDate));
Sort of sorted (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());
Multi-sorted (solution)
return trade.stream()
.filter(t -> !isExcluded(t))
.sorted(comparing(Trade::getNetAmount)
.thenComparing(Trade::getCUSIP)
.thenComparing(Trade::getDate))
.collect(toList());
Top twenty words (Ugly)
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());
I must use streams (Ugly)
combinedList.addAll(
balances.stream().collect(Collectors.toList()));
List<Trade> allTrades = new ArrayList<>();
trades1.forEach(t -> allTrades.add(t));
trades2.forEach(t -> allTrades.add(t));
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) {
Q & A
Peter Lawrey
http://vanillajava.blogspot.com/
@PeterLawrey