Map<String, List<Employee>> myMap = new HashMap<>();
for (int j = 0; j < (MAX_SALARY - MIN_SALARY) / value; j++) {
List<Employee> list = new ArrayList<>();
for (Employee emp : employees) {
if (emp.getSalary() >= (j + 1) * value && emp.getSalary() < (j + 2) * value)
list.add(emp);
}
myMap.put(Integer.toString((j + 1) * value) + "-" + Integer.toString((j + 2) * value), list);
}
for (String key : myMap.keySet()) {
System.out.println(key + " -> " + myMap.get(key).size());
}
Итак, задача состоит в том, чтобы из списка сотрудников составить Map
, ключом которого будет интервал зарплат, а значением - список сотрудников, чьи зарплаты попадают в этот интервал.
Попробуем для начала реализовать это "наивно". Цикл
for (int j = 0; j < (MAX_SALARY - MIN_SALARY) / value; j++)
можно заменить на IntStream
:
IntStream.range(0, (MAX_SALARY - MIN_SALARY) / value)
Сотрудников, чья зарплата входит в интервал [(j + 1) * value, (j + 2) * value)
, можно вычленить так:
employees
.stream()
.filter(e -> e.getSalary() >= (j + 1) * value && e.getSalary() < (j + 2) * value)
.collect(Collectors.toList())
Сложить их в Map
можно при помощи Collectors.toMap()
:
Collectors.toMap(
i -> (j + 1) * value + "-" + (j + 2) * value,
i -> employees
.stream()
.filter(e -> e.getSalary() >= (j + 1) * value && e.getSalary() < (j + 2) * value)
.collect(Collectors.toList()))
Складывая всё вместе, получаем
Map<String, List<Employee>> map = IntStream.range(0, (MAX_SALARY - MIN_SALARY) / value)
.boxed() // Нужно, чтобы перейти от IntStream
// к обычному Stream, в котором доступна
// нужная нам перегрузка метода collect()
.collect(Collectors.toMap(
i -> (i + 1) * value + "-" + (i + 2) * value,
i -> employees
.stream()
.filter(e -> e.getSalary() >= (i + 1) * value && e.getSalary() < (i + 2) * value)
.collect(Collectors.toList())));
Немножко подчищаем и оптимизируем код:
Map<String, List<Employee>> map = IntStream.range(0, (MAX_SALARY - MIN_SALARY) / value)
.map(i -> (i + 1) * value)
.boxed()
.collect(Collectors.toMap(
i -> i + "-" + (i + value),
i -> employees
.stream()
.filter(e -> e.getSalary() >= i)
.filter(e -> e.getSalary() < i + value)
.collect(Collectors.toList())));
Готово! Теперь идём в документацию и читаем о Collectors.groupingBy()
. С учётом прочитанного переписываем наш код так:
Map<String, List<Employee>> map = employees.stream()
.collect(Collectors.groupingBy(
e -> e.getSalary() / value * value + "-" + (e.getSalary() / value + 1) * value));
e.getSalary() / value * value
и (e.getSalary() / value + 1) * value
позволяют определить границы интервала, в который попадает зарплата. Благодаря целочисленному делению, e.getSalary() / value * value
не обязательно равно e.getSalary()
.
Получаем почти такой же результат, как в оригинале. Почти - потому что отсутствуют диапазоны, в которые не попадает ни один сотрудник. Исправляем это недоразумение:
Map<String, List<Employee>> map = employees.stream()
.filter(e -> e.getSalary() >= MIN_SALARY && e.getSalary() <= MAX_SALARY)
.collect(Collectors.groupingBy(e -> e.getSalary() / value * value + "-" + (e.getSalary() / value + 1) * value));
IntStream.range(0, (MAX_SALARY - MIN_SALARY) / value)
.map(i -> (i + 1) * value)
.mapToObj(i -> i + "-" + (i + value))
.filter(key -> !map.containsKey(key))
.forEach(key -> map.put(key, Collections.emptyList()));
Всё, теперь результат в точности такой же, как и в оригинале.
Впрочем, советую дважды подумать, прежде чем переписывать код таким образом. Обычно стримы используют для того чтобы повысить читаемость кода, описать что вы хотите сделать, а не как. В данном случае повышения читаемости я не наблюдаю, наоборот, код становится более запутанным. Переписывание на стримы хорошо работает при обработке коллекции одним циклом, но вложенные циклы на стримах читаются тяжелее.
На сколько я понял ваш код, вы пытаетесь получить количество сотрудников по диапазонам зарплат.
Map<String, Long> map =
employees.stream()
.map(Employee::getSalary)
.collect(Collectors.groupingBy(
salary -> ((salary + 1) * value) + "-" + ((salary + 2) * value),
Collectors.counting()))
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Имеется переменная типа String "daily - ежедневный"Нужно вывести сначала "daily", а потом "ежедневный"
Добрый день смотрю разные схемы mvp + clean ,так вот в одной из этих реализаций видел некую особеннось где была схема Repository/Gateway -> converter->api
В первый раз столкнулся с JavaScript и не могу понять, как мне передать Map в JavaScript