伙计们,
考虑以下示例,给定一个Trade对象列表,我的代码需要返回一个包含交易量24小时,7天,30天和所有时间的数组.
使用普通的旧迭代器,这只需要对集合进行一次迭代.
我正在尝试使用Java 8流和Lambda表达式来做同样的事情.我想出了这个代码,它看起来很优雅,工作正常,但需要在列表上进行4次迭代:
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};
}
如何在列表中仅使用一次迭代来实现相同的目标?
解决方法
此问题类似于“摘要统计信息”收集器.看一下IntSummaryStatistics类:
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);
}
...
}
它旨在与collect()一起使用;这是IntStream.summaryStatistics()的实现
public final IntSummaryStatistics summaryStatistics() {
return collect(IntSummaryStatistics::new,IntSummaryStatistics::accept,IntSummaryStatistics::combine);
}
编写像这样的收集器的好处是您的自定义聚合可以并行运行.