Как создать новый объект из группировки по результату - PullRequest
0 голосов
/ 04 мая 2020

Для примера в Java 8 объектов POJO фильтруют pojo на основе общей комбинации нескольких клавиш и суммы в одном поле

Подведя итоги, мне нужно создать новый объект Тип продаж, имеющий итоги (результат суммирования группы по) Что-то вроде ниже

{
"month" : "Total",
"year":  "2000",
"state" : "State1",
"city" :  "City1",
"sales" : "15"
}

Итак, я создал соответствующий конструктор в Продажах и попробовал

list.stream()
    .collect(groupingBy(Sale::getState,
                        groupingBy(Sale::getCity,
                                   summingInt(Sale::getSales).Collectors.mapping(e -> new Sales ("Total","2000","State1","City1",<summingInt result should come here>),
                                Collectors.toList()))));  

Как мне достичь чего-то вроде выше формат в Java 8?

Ответы [ 2 ]

1 голос
/ 04 мая 2020

Ваше направление правильное. Единственное, что нужно сделать, это последний шаг, который объединяет все номера продаж в один объект. Вы не можете просто использовать summingInt, потому что он возвращает только int, а у вас нет других полей для создания объекта. Вы можете добиться этого, используя reduce для создания начального объекта и добавляя значение поля:

list.stream()
    .collect(groupingBy(Sale::getState,
                        groupingBy(Sale::getCity,
                                   reducing( (a, b) -> new Sale(a.getMonth(), a.getYear(), a.getState(), a.getCity(), a.getSale() + b.getSale()) ))));

Если вам не важны месяц и год, вы также можете создать объект идентификации (начальный объект ) и добавить к нему только продажи. Это может уменьшить количество создаваемых временных объектов:

list.stream()
    .collect(groupingBy(Sale::getState,
                        groupingBy(Sale::getCity,
                                   reducing(new Sale("Total", "2000", "", "", 0), (a, b) -> {
                                            a.setState(b.getState());
                                            a.setCity(b.getCity()); 
                                            a.setSales(a.getSales() + b.getSales()); 
                                            return a;
                                   } ))));

Убедитесь, что ваш год и месяц одинаковы для всех объектов, иначе он будет утерян (если вам не все равно).

1 голос
/ 04 мая 2020

Вы можете сделать так:

вместо второго groupingBy вы можете использовать toMap сборщик с функцией слияния.

list.stream()
    .collect(Collectors.groupingBy(Sales::getState,
        Collectors.toMap(Sales::getCity,Function.identity(),                              
              (s1, s2) -> new Sales(s1.month,...,s1.getSales() + s2.getSales()))));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...