我有一个整数列表 list1,我想得到另一个列表 list2,它将包含从开始到当前索引的累积总和。如何使用 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));
}
如何将上面的命令式代码更改为声明式?
list2 should be [1, 3, 6, 10]
最佳答案
Streams 不适合这种任务,因为涉及到状态(累积部分和)。相反,您可以使用 Arrays.parallelPrefix
:
Integer[] arr = list1.toArray(Integer[]::new);
Arrays.parallelPrefix(arr, Integer::sum);
List<Integer> list2 = Arrays.asList(arr);
这首先使用 Collection.toArray
将 list1
复制到一个数组中,自 JDK 11 起可用。如果您尚未使用 Java 11,则可以将第一行替换为传统的 toArray
调用:
Integer[] arr = list1.toArray(new Integer[0]);
此解决方案不使用流,但它是声明式,因为Arrays.parallelPrefix
接收累积操作作为参数(Integer::sum
在这种情况下)。
时间复杂度为 O(N)
,但在设置并行处理所需的基础设施时可能会涉及一些非常小的恒定成本。但是,根据文档:
Parallel prefix computation is usually more efficient than sequential loops for large arrays
因此看来值得一试这种方法。
此外,值得一提的是,这种方法之所以有效,是因为 Integer::sum
是一个关联运算。这是一个要求。
关于java - 使用 Java 8 流 API 的累积和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55265797/