避免多次迭代的 Java Lambda 表达式

标签 java lambda java-8 java-stream

各位,

考虑以下示例,给定一个 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);
}

像这样编写 Collector 的好处是您的自定义聚合可以并行运行。

关于避免多次迭代的 Java Lambda 表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24407931/

相关文章:

java - HAPI v2.0 Hl7消息

java - 如何从 EJB 捕获运行时异常?

python - 将变量转换为lambda中另一个变量的类型

multithreading - 在 C++ 多线程应用程序中,我应该传递 lambda 还是带参数的函数?

java - 使用 java 8 流查找平均值

java - Spring ACL 是一个好的 ACL 实现吗?

java - Graphics2D 到 BufferedImage

java - 使用java从Windows访问个人证书

java - Java8 thenCompose 和 thenComposeAsync 之间的区别

java - 基于注释参数创建切入点