Найти средний возраст мужчин в списке

14. Найти средний возраст мужчин в списке

Условие задачи:
Дан список объектов Person с полями:

  • name;

  • age;

  • sex.

Необходимо с помощью Stream API найти средний возраст всех мужчин из списка.

Если мужчин в списке нет, результат должен быть пустым OptionalDouble.

Код:

List<Person> persons = Arrays.asList(
        new Person("Alice", 25, "female"),
        new Person("Bob", 30, "male"),
        new Person("Eve", 35, "female"),
        new Person("Jack", 28, "male")
);

Пример результата:

29.0

Если мужчин нет:

OptionalDouble.empty

Спойлеры к решению

Подсказки
💡 Через filter() оставь только мужчин.
💡 Через mapToInt() преобразуй поток Person в поток возрастов.
💡 Метод average() возвращает OptionalDouble.
💡 OptionalDouble позволяет корректно обработать случай, когда подходящих элементов нет.

Решение
OptionalDouble averageAgeOfMales = persons.stream()
        .filter(person -> "male".equalsIgnoreCase(person.getSex()))
        .mapToInt(Person::getAge)
        .average();

Сначала:

.filter(person -> "male".equalsIgnoreCase(person.getSex()))

оставляет только мужчин.

Вызов equalsIgnoreCase() выполняется у строкового литерала "male", поэтому код не выбросит NullPointerException, если person.getSex() вернёт null.

Затем:

.mapToInt(Person::getAge)

преобразует объекты Person в их возраст, а:

.average()

вычисляет среднее значение и возвращает OptionalDouble.

Для возрастов 30 и 28 результат:

29.0

Если мужчин в списке нет, average() вернёт:

OptionalDouble.empty

Если по условию обязательно требуется получить именно double, можно задать значение для случая отсутствия мужчин:

double averageAgeOfMales = persons.stream()
        .filter(person -> "male".equalsIgnoreCase(person.getSex()))
        .mapToInt(Person::getAge)
        .average()
        .orElse(0.0);

Но если отсутствие мужчин должно отличаться от реального среднего возраста 0, предпочтительнее сохранить OptionalDouble.

Временная сложность — O(n), дополнительная память — O(1).