20. Посчитать общую зарплату уникальных руководителей сотрудников старше 40 лет
Условие задачи:
Дан список сотрудников employees.
Каждый сотрудник содержит:
имя;
возраст;
зарплату;
множество руководителей
heads.
Необходимо найти общую зарплату всех руководителей сотрудников, возраст которых больше 40 лет.
Один и тот же руководитель может быть указан у нескольких сотрудников. В таком случае его зарплата должна учитываться только один раз.
Код:
@Data
class User {
private String name;
private int age;
private double salary;
private Set<User> heads;
}
List<User> employees = ...;
Спойлеры к решению
Подсказки
💡 Сначала необходимо оставить только сотрудников старше 40 лет.
💡 У каждого сотрудника находится коллекция heads, поэтому для получения одного общего потока руководителей можно использовать flatMap().
💡 Один руководитель может встречаться у нескольких сотрудников. Перед суммированием необходимо удалить дубликаты.
💡 Для получения общей зарплаты удобно преобразовать поток в DoubleStream с помощью mapToDouble().
Решение
Сначала отфильтруем сотрудников по возрасту:
.filter(employee -> employee.getAge() > 40)
После этого получим всех их руководителей.
Поскольку getHeads() возвращает Set<User>, для объединения руководителей всех сотрудников в один поток используем flatMap():
.flatMap(employee -> employee.getHeads().stream())
Один и тот же руководитель может присутствовать у нескольких сотрудников, поэтому используем distinct().
Итоговое решение:
double totalSalary = employees.stream()
.filter(employee -> employee.getAge() > 40)
.flatMap(employee -> employee.getHeads().stream())
.distinct()
.mapToDouble(User::getSalary)
.sum();
Полный пример:
import lombok.Data;
import java.util.List;
import java.util.Set;
public class Main {
public static void main(String[] args) {
List<User> employees = ...;
double totalSalary = employees.stream()
.filter(employee -> employee.getAge() > 40)
.flatMap(employee -> employee.getHeads().stream())
.distinct()
.mapToDouble(User::getSalary)
.sum();
System.out.println(totalSalary);
}
}
@Data
class User {
private String name;
private int age;
private double salary;
private Set<User> heads;
}
Разберём pipeline:
employees
↓
filter(age > 40)
↓
получаем heads каждого сотрудника
↓
flatMap()
↓
единый поток руководителей
↓
distinct()
↓
уникальные руководители
↓
mapToDouble(User::getSalary)
↓
sum()
Например, если есть сотрудники:
Employee 1, age = 45 → heads: [Head A, Head B]
Employee 2, age = 50 → heads: [Head A, Head C]
а зарплаты руководителей:
Head A → 100 000
Head B → 150 000
Head C → 200 000
то Head A встречается два раза, но его зарплата должна учитываться только один раз.
Результат:
100 000 + 150 000 + 200 000 = 450 000
Важный момент с distinct()
#
Метод:
distinct()
определяет уникальность объектов через equals() и hashCode().
Поскольку используется Lombok-аннотация:
@Data
Lombok генерирует equals() и hashCode() автоматически.
Однако в реальном приложении стоит внимательно определить, по каким полям два пользователя считаются одним и тем же человеком. Обычно для этого лучше использовать уникальный идентификатор пользователя, а не все поля объекта.
Сложность #
При условии корректной реализации hashCode():
время — примерно
O(n + h), гдеn— количество сотрудников, аh— общее количество рассматриваемых руководителей;дополнительная память —
O(k), гдеk— количество уникальных руководителей, которое необходимо хранить для работыdistinct().