Рассчитать сумму значений HashMap

Подскажите пожалуйста, следующий момент.

Есть хэш – таблица вида HashMap<Integer, List<Objects>>

Ключи — это порядковый номер кабинета с 1. Всего кабинетов 5.

В значениях List<Objects> хранятся значения двух типов String и Integer. ФИО сотрудника (String fullName) и размер заработной платы (Integer salary) соответственно.

Пример:

    Иванов Иван Иванович 50000
    Петров Павел Павлович 38000
    Семенов Семен Семенович 58000

Не могу понять, как получить сумму зарплат сотрудников по кабинетам.

Есть идея, что нужно в методе по получению суммы зарплат, который получается должен в качестве аргумента принимать основную мапу, создать новый HashMap<Integer, Integer> и заполнять его из List<Objects> основной мапы суммами зарплат по кабинету в качестве значений и номерами кабинетов в качестве ключей циклом for (int i = 0; i < 5; i++), каждую итерацию записывая данные в новую мапу метода. А уж потом с этой хэш - таблицей работать по желанию. Вижу решение так, но не могу понять именно реализацию непосредственно по коду.

Дополнение:

Решаю небольшую разновидность задачи, со считыванием данных в которой Дмитрий мне очень помог ранее.

https://ru.stackoverflow.com/a/1399756/491343

Метод psmv в его примере я заменил на нестатический метод.

Также в этом классе создал HashMap<Integer, List<Objects>> totalStats, который инициализируется в конструкторе класса. В классе Main у меня метод psvm, в котором меню с выбором действий, в том числе считывание данных и планируемое их сравнение и т.д..

В цикле по списку filesList убрал печать и добавил метод totalStats.put(K key, V value), который используя информацию из названия пути файла с нужным индексом в качестве ключа пока не закончатся файлы, заполняет HashMap<1, List<Objects>> , HashMap<2, List<Objects>> и т.д..

List<Objects> как раз и получается после парсинга csv через вспомогательный класс.

class Objects {


    private final String fullName;
    private final Integer salary;

    public Objects(String[] columns) {
        this.fullName = columns[0];
        this.salary = Integer.valueOf(columns[1]);
    }

    public String getFullName() {
        return fullName;
    }


    public Integer getSalary() {
        return salary;
    }

}

Считывание работает, судя по дебагу мапы, информация успешно заносится по ключам и значениям, во всяком случае на мой взгляд зелёного новичка.

И вот не могу понять, как найти сумму зарплат из первого кабинета, из второго кабинета и т.д., чтобы они также хранилась в отдельной HashMap и на время работы программы я мог получать эти значения по ключу (номеру кабинета).

Количество кабинетов может быть разное, но на момент анализа данных парсинг уже должен быть сделан (потом сделаю проверку основой мапы методом hashMap.isEmpty(), это не проблема), поэтому, как я думаю, количество итераций при заполнении циклом новой мапы с суммами зарплат по кабинетам HashMap<Integer, Integer> sumSalaryOffices должно быть в диапазоне от i = 0 до i < totalStats.size().

Не получается разобраться как реализовать это, т.е. как работать с переменными List<Objects>, чтобы, получить суммы интересующих меня переменных (геттер getSalary в классе Objects есть) и сохранить их в HashMap<Integer, Integer> sumSalaryOffices.

Проще говоря, если, например, для HashMap<Integer, List<Objects>> totalStats воспользоваться методом totalStats.get(1); я получу List<Objects> для первого кабинета, уже разбитым по переменным благодаря классу Objects. Во всяком случае при дебаге в IDEA выглядит всё неплохо.

Далее мне нужно сложить все значения Integer salary по данному кабинету, занести их в HashMap sumSalaryOffices методом sumSalaryOffices.put(1, 146000). И так пройтись по всем имеющимся кабинетам.

А потом уже работать с данной мапой (sumSalaryOffices) как мне вздумается.


Ответы (1 шт):

Автор решения: Nowhere Man

Задача сводится к итерации по спискам-значениям внутри хэш-таблицы, то есть, к использованию вложенного цикла: 0) Создать результирующую хэш-таблицу для хранения сумм

  1. Внешний цикл -- по парам "ключ-значение" внутри хэш-таблицы, которые представлены в виде Map.Entry<Integer, List<Objects>> и могут быть получены при помощи метода Map::entrySet
  2. Внутренний цикл -- расчёт суммы зарплат и запись в результат как показано ниже.

В представленном коде для расчёта/записи суммы в результат используется метод Map::merge

public static Map<Integer, Integer> countTotalSalary(Map<Integer, List<Objects>> input) {
    Map<Integer, Integer> result = new HashMap<>();
    for (Map.Entry<Integer, List<Objects>> entry : input) {
        for (Objects personSalary : entry.getValue()) {
            result.merge(entry.getKey(), personSalary.getSalary(), Integer::sum);
        }
    }
    return result;
}

Аналогичный код с использованием Stream API:

public static Map<Integer, Integer> countTotalSalary(Map<Integer, List<Objects>> input) {
    return input.entrySet().stream() // Stream<Map.Entry<Integer, List<Objects>>>
        .collect(Collectors.toMap(
            Map.Entry::getKey,
            e -> e.getValue().stream() // Stream<Objects>
                .map(Objects::getSalary) // Stream<Integer>
                .reduce(0, Integer::sum) // Integer
        ));
}

Оба вышеприведённых примера кода используют функциональные методы / потоки, появившиеся в Java 8. Более простой пример:

public static Map<Integer, Integer> countTotalSalary(Map<Integer, List<Objects>> input) {
    Map<Integer, Integer> result = new HashMap<>();
    for (Map.Entry<Integer, List<Objects>> entry : input) {
        int total = 0;
        for (Objects personSalary : entry.getValue()) {
            total += personSalary.getSalary();
        }
        result.put(entry.getKey(), total);
    }
    return result;
}
→ Ссылка