Home > Blockchain >  How to loop in the list and apply an Arithmetic operation of different keys elements and calculate t
How to loop in the list and apply an Arithmetic operation of different keys elements and calculate t

Time:03-18

I have class DTO which have 4 fields.

And I have a list of DTO objects.

I want to do an arithmetic operation with values of the elements with the same dataPeriod. As a final result I need to generate computed result and create new DTO, see the below example. How to apply formula using Java 8 and Stream

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

Below list i have orderBy dataPeriod that is why is look like this so that my formula works correctly.

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));

I want to apply the below formula for by loop in all the dataPeriod like below we have 5:

I have done using normal java code but how to do the same using java 8 and Stream may be here we can use Recursive function but how? Any one can please help me for this. Thanks in advance!!

NOTE:- Into the formula A always come first in the list otherwise wrong result will be given.

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));
 }

***Expected OP: ***

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

CodePudding user response:

You can use an IntStream to iterate the indexes of the list and then reduce with d1, d2) -> d1 - d2 using 0 as identity:

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);

Alternatively, you can stream the list and collect using Collectors.groupingBy with DTO::getDataPeriod classifier, and mapping values using DTO::getValue.

Then you can stream the values of the resulting Map<Integer, Double>, convert the stream to DoubleStream, and reduce using sum().

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);
  • Related