使用Java 8流API的累积总和 [英] Cumulative Sum using Java 8 stream API

查看:50
本文介绍了使用Java 8流API的累积总和的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个整数列表,例如list1,我想获得另一个列表list2,该列表将包含从开始到当前索引为止的累积总和.如何使用Stream API Java 8做到这一点?

I have a List of Integer say list1, and I want to get another list list2 which will contain the cumulative sum up until the current index from start. How can I do this using Stream API java 8 ?

List<Integer> list1 = new ArrayList<>();
list1.addAll(Arrays.asList(1, 2, 3, 4));
List<Integer> list2 = new ArrayList<>();
// initialization
list2.add(list1.get(0));
for(int i=1;i<list1.size();i++) {
// increment step
    list2.add(list2.get(i-1) + list1.get(i));
}

如何将以上命令式代码更改为声明式?

How can I change above imperative style code into declarative one ?

list2 should be [1, 3, 6, 10]

推荐答案

流不适合此类任务,因为其中涉及状态(累计部分和).相反,您可以使用

Streams are not suited for this kind of task, as there is state involved (the cumulative partial sum). Instead, you could use Arrays.parallelPrefix:

Integer[] arr = list1.toArray(Integer[]::new);

Arrays.parallelPrefix(arr, Integer::sum);

List<Integer> list2 = Arrays.asList(arr);

这首先使用list1复制到数组.html#toArray(java.util.function.IntFunction)"rel =" noreferrer> Collection.toArray ,自JDK 11开始可用.如果尚未使用Java 11,则可以替换第一行与传统的toArray通话:

This first copies list1 to an array by using Collection.toArray, which is available since JDK 11. If you are not on Java 11 yet, you could replace the first line with the traditional toArray call:

Integer[] arr = list1.toArray(new Integer[0]);

此解决方案不使用流,而是声明式,因为Arrays.parallelPrefix将累积运算作为参数接收(在这种情况下为Integer::sum).

This solution doesn't use streams, yet it's declarative, because Arrays.parallelPrefix receives the cumulative operation as an argument (Integer::sum in this case).

时间复杂度为O(N),尽管与设置并行处理所需的基础结构可能涉及一些非微小的固定成本.但是,根据文档:

Time complexity is O(N), though there might be some non-minor constant costs involved associated with setting up the infrastructure needed for parallel processing. However, according to the docs:

对于大型数组,并行前缀计算通常比顺序循环更有效

Parallel prefix computation is usually more efficient than sequential loops for large arrays

因此,似乎值得尝试这种方法.

So it seems it's worth giving this approach a try.

此外,值得一提的是,该方法有效,因为Integer::sum关联操作.这是必需的.

Also, it's worth mentioning that this approach works because Integer::sum is an associative operation. This is a requirement.

这篇关于使用Java 8流API的累积总和的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆