如何在列表中循环并应用不同键元素的算术运算并使用 Java 8 和递归计算最终值

How to loop in the list and apply an Arithmetic operation of different keys elements and calculate the final value using Java 8 and Recursion

我有 class DTO 有 4 个字段。

我有一个包含 DTO 个对象的列表。

我想对具有 相同 的元素的 进行 算术运算 数据周期。作为最终结果,我需要生成计算结果并创建新的 DTO,请参见下面的示例。如何使用 Java 8Stream

应用公式
@lombok.Data
@AllArgsConstructor
static class DTO {
    String key;
    int dataPeriod;
    int year;
    Double value;
}

下面的列表我有 orderBy dataPeriod 这就是为什么它看起来像这样我的公式才能正常工作。

list.add(new DTO("A", 1, 2020, 5.0));
list.add(new DTO("B", 1, 2020, -9.0));

list.add(new DTO("A", 2, 2020, 8.0));
list.add(new DTO("B", 2, 2020, 3.5));

list.add(new DTO("A", 3, 2020, 1.5));
list.add(new DTO("B", 3, 2020, 7.0));

list.add(new DTO("A", 4, 2020, -6.0));
list.add(new DTO("B", 4, 2020, 5.0));

list.add(new DTO("A", 5, 2020, 1.5));
list.add(new DTO("B", 5, 2020, -7.0));

我想在所有 dataPeriod 循环中应用下面的 公式 for by 循环,如下所示我们有 5:

我已经使用普通的 java 代码完成了,但是如何使用 java 8Stream 可能在这里我们可以使用 递归函数 但是如何呢?任何人都可以为此帮助我。 提前致谢!!

注意:- 进入公式 A 总是在列表中排在第一位,否则会给出错误的结果。

C = C - (A[i] - B[i]) [where i is dataPeriod and initial value of C is ZERO]

 public static void main(String[] args) {
    Double C = 0.0;
       for (int i = 0; i < list.size() / 2; i++) {
           C = C - (list.get(i * 2).getValue() - list.get(i * 2 + 1).getValue());
       }

    System.out.println(new DTO("C", 0, 2020, C));
 }

*** 预期 OP:***

Test.DTO(key=C, dataPeriod=0, year=2020, value=-10.5)

您可以使用 IntStream 迭代 list 的索引,然后使用 0 作为身份与 d1, d2) -> d1 - d2 进行归约:

double c = IntStream.iterate(0, i -> i + 2)
        .limit(list.size() / 2)
        .mapToDouble(i -> list.get(i).getValue() - list.get(i + 1).getValue())
        .reduce(0d, (d1, d2) -> d1 - d2);

DTO dto = new DTO("C", 0, 2020, c);

或者,您可以 stream list 并使用 Collectors.groupingByDTO::getDataPeriod 分类器进行收集,并使用 DTO::getValue.[=26= 映射值]

然后您可以 stream 结果 Map<Integer, Double> 的值,将 stream 转换为 DoubleStream,并使用 sum().[=26 减少=]

double c = list.stream().collect(Collectors.groupingBy(DTO::getDataPeriod, 
        Collectors.mapping(DTO::getValue, 
                Collectors.reducing(0d, (v1, v2) -> v2 - v1))))
        .values().stream()
        .mapToDouble(Double::doubleValue)
        .sum();

DTO dto = new DTO("C", 0, 2020, c);