У меня есть классDTO
с 4 полями.
И у меня есть список DTO
объектов.
Я хочу сделать арифметическая операция с ценности элементов с такой жедатаПериод. В качестве окончательного результата мне нужно сгенерировать вычисленный результат и создать новый DTO
, см. пример ниже. Как применить формулу с использованием Ява 8 и Поток
@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));
Я хочу применить приведенный ниже формула для цикла by во всех датаПериод, как показано ниже, у нас есть 5:
Я сделал это, используя обычный код Java, но как сделать то же самое, используя джава 8 и Поток, здесь мы можем использовать Рекурсивная функция, но как? Любой может помочь мне в этом. Заранее спасибо!!
ПРИМЕЧАНИЕ:- В формуле 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));
}
*** Ожидаемый ОП: ***
Test.DTO(key=C, dataPeriod=0, year=2020, value=-10.5)
@ernest_k обновил, спасибо за комментарий :)
Спасибо. А вторая часть про поле?
@ernest_k Я хочу применить формулу для одного и того же периода данных для другого ключа в значении.
Вам не нужны потоки здесь, просто держите их.
@RavindraRanwala Спасибо за ваш комментарий, но я знаю, что это возможно при использовании java 8 и потоковой передачи.
Вы можете использовать IntStream
для итерации индексов list
, а затем уменьшить с помощью d1, d2) -> d1 - d2
, используя 0
в качестве идентификатора:
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.groupingBy
с классификатором DTO::getDataPeriod
, и сопоставлять значения с помощью DTO::getValue
.
Затем вы можете stream
получить значения Map<Integer, Double>
, преобразовать stream
в DoubleStream
и уменьшить с помощью 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);
Спасибо @Oboe, какие изменения требуются, если мои значения в BIgDecimal? На самом деле я сделал тестовые сценарии из своего реального кода.
Потому что функция Map to BigDecimal не в java
@Rishi Kumar Да, в случае IntStream
вместо mapToDouble
вам пришлось бы сопоставлять mapToObj
с list.get(i).getValue().subtract(list.get(i + 1).getValue())
. Затем уменьшите с помощью .reduce(BigDecimal.ZERO, (d1, d2) -> d1 .subtract(d2))
. Во втором случае вам придется заменить Collectors.reducing(0d, (v1, v2) -> v2 - v1))
на Collectors.reducing(BigDecimal.ZERO, (v1, v2) -> v2 .subtract(v1))
, а sum()
заменить на reduce(BigDecimal.ZERO, (v1, v2) -> v1 .subtract(v2))
.
Ваша формула говорит
C - (A[i] * B[i])
, но ваш код делаетC - (A[i] - B[i])
. Кроме того, в вашем тексте говорится, что используетсяdataPeriod
, но код тянетgetValue()
. Что он?