Java lambda expressions avoid multiple iterations
Guys,
Consider the following example. Given a list of trade objects, my code needs to return an array containing transaction volume, 24 hours, 7 days, 30 days and all times
Using a normal old iterator, this requires only one iteration of the collection
I'm trying to do the same thing with Java 8 streams and lambda expressions I came up with this code. It looks elegant and works normally, but it needs four iterations on the list:
public static final int DAY = 24 * 60 * 60; public double[] getTradeVolumes(List<Trade> Trades,int timeStamp) { double volume = Trades.stream().mapToDouble(Trade::getVolume).sum(); double volume30d = Trades.stream().filter(Trade -> Trade.getTimestamp() + 30 * DAY > timeStamp).mapToDouble(Trade::getVolume).sum(); double volume7d = Trades.stream().filter(Trade -> Trade.getTimestamp() + 7 * DAY > timeStamp).mapToDouble(Trade::getVolume).sum(); double volume24h = Trades.stream().filter(Trade -> Trade.getTimestamp() + DAY > timeStamp).mapToDouble(Trade::getVolume).sum(); return new double[]{volume24h,volume7d,volume30d,volume}; }
How do I use only one iteration in the list to achieve the same goal?
Solution
This problem is similar to the summary statistics collector Take a look at the intsummarystatistics class:
public class IntSummaryStatistics implements IntConsumer { private long count; private long sum; ... public void accept(int value) { ++count; sum += value; min = Math.min(min,value); max = Math.max(max,value); } ...
}
It is intended for use with collect(); This is intstream Implementation of summarystatistics()
public final IntSummaryStatistics summaryStatistics() { return collect(IntSummaryStatistics::new,IntSummaryStatistics::accept,IntSummaryStatistics::combine); }
The advantage of writing collectors like this is that your custom aggregates can run in parallel