Как зациклить список и применить арифметическую операцию к различным элементам ключей и вычислить конечное значение с помощью Java 8 и рекурсии

У меня есть класс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)

Ваша формула говорит C - (A[i] * B[i]), но ваш код делает C - (A[i] - B[i]). Кроме того, в вашем тексте говорится, что используется dataPeriod, но код тянет getValue(). Что он?

ernest_k 17.03.2022 14:42

@ernest_k обновил, спасибо за комментарий :)

Rishi Kumar 17.03.2022 14:44

Спасибо. А вторая часть про поле?

ernest_k 17.03.2022 14:45

@ernest_k Я хочу применить формулу для одного и того же периода данных для другого ключа в значении.

Rishi Kumar 17.03.2022 14:47

Вам не нужны потоки здесь, просто держите их.

Ravindra Ranwala 17.03.2022 14:50

@RavindraRanwala Спасибо за ваш комментарий, но я знаю, что это возможно при использовании java 8 и потоковой передачи.

Rishi Kumar 17.03.2022 14:53
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
6
66
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете использовать 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);

В качестве альтернативы вы можете streamlist и собирать, используя 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? На самом деле я сделал тестовые сценарии из своего реального кода.

Rishi Kumar 17.03.2022 15:54

Потому что функция Map to BigDecimal не в java

Rishi Kumar 17.03.2022 16:00

@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)).

Oboe 17.03.2022 16:18

Другие вопросы по теме