Как выполнить группирование, подсчет и суммирование из списка объектов в одном потоке и сохранение в другом списке объектов? - PullRequest
5 голосов
/ 21 апреля 2019

Я пытаюсь получить группу по количеству и сумме из списка объектов, используя поток Java и коллекцию. Я не уверен, как мне достичь желаемого результата.

InputModel

String month;
BigDecimal salary;
String department;
String noOfEmp;

InputModel [(май 100, IT, 10), (июнь 300, IT, 7), (июль 300, IT, 7), (май 1000, HR, 5), (июнь 300, HR-, 7), (июль, 600, HR, 5)]

OutputModel

String month
BigDecimal salary
String noOfEmp

Ожидаемый результат OutputModel [(май, 1100,15), (июнь, 600,14), (июль, 900,12)]

Я попробовал приведенный ниже код, но он вернул группу и количество.

Map<String, Integer> result= inputModels.parallelStream().collect(Collectors.groupingBy(InputModel::getMonth,
            LinkedHashMap::new, Collectors.summingInt(InputModel::getNoOfEmp)));

Заранее спасибо !!!

Ответы [ 2 ]

6 голосов
/ 21 апреля 2019

Если у вас есть класс OutputModel, это решит вашу проблему.

Collection<OutputModel> outputModels = inputModel.stream()
    .map(im -> new OutputModel(im.getMonth(), im.getSalary(), im.getNoOfEmp()))
    .collect(Collectors.toMap(OutputModel::getMonth, Function.identity(),
        (m1, m2) -> new OutputModel(m1.getMonth(), m1.getSalary().add(m2.getSalary()),
            String.valueOf(Integer.valueOf(m1.getNoOfEmp()) + Integer.valueOf(m2.getNoOfEmp()))),
        LinkedHashMap::new))
    .values();

Слово предостережения: лучше НЕ использовать строки, если другие типы более уместны. Например, вы должны были использовать int для представления noOfEmp вместо String. Это упростит код, уменьшая вероятность ошибок во время выполнения из-за ложных данных. Кроме того, рассмотрите возможность использования java.time.Month enum для представления месяца года, в отличие от использования строковых литералов.

Вот вывод,

[{месяц = ​​май, зарплата = 1100, noOfEmp = 15}, {месяц = ​​июнь, зарплата = 600, noOfEmp = 14}, {месяц = ​​июль, зарплата = 900, noOfEmp = 12}]

3 голосов
/ 21 апреля 2019

вы можете комбинировать groupingBy и reducing

Map<String, Optional<OutputModel>> outputModels = inputModel.stream()
            .map(ip -> new OutputModel(ip.getMonth(), ip.getSalary(), ip.getNoOfEmp()))
            .collect(Collectors.groupingBy(OutputModel::getMonth, 
                           LinkedHashMap::new, 
                           Collectors.reducing(OutputModel::merge)));

//the following method goes into OutputModel
public static OutputModel merge(OutputModel o1, OutputModel o2) {
        return new OutputModel(o1.month, o1.salary.add(o1.salary), o1.noOfEmp + o2.noOfEmp);
}

Я использовал LinkedHashMap, поэтому порядок вставки будет сохранен, также я изменил noOfEmp на Integer

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...