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