java - 使用 Java 8 流 API 的累积和

标签 java java-8 java-stream

我有一个整数列表 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.toArraylist1 复制到一个数组中,自 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/

相关文章:

java-8 - java 8 - 如何通过使用方法来抽象谓词的使用

java - 打破听众的递归

Java 8 流和 map 值得吗?

java - Java 的 Stream.flatMap() 的(某种)逆操作是什么?

java - 通过添加类的两个 BigDecimal 类型属性进行分组

Java 客户端无法通过 HTTPS 使用 SSL 访问 Web 服务

java - Vert.x java List<Futures> 参数化

java - 尝试从从 sqlite 中提取的对象列表中调用方法时的空对象引用

java流逗号分隔

spring-boot - @AllArgsConstructor 和构造函数注入(inject) Spring : is private final needed?