Группировать список объектов по свойству и вычислять среднее значение свойства объекта по ключу - PullRequest
0 голосов
/ 19 октября 2018

Допустим, у меня есть класс Person:

class Person {
    String firstName;
    String age;

    public String getFirstName() {
        return firstName;
    }

    public String getAge() {
        return age;
    }
}

У меня есть List<Person> в качестве ввода.В качестве результата я хотел бы получить DoubleStream среднего возраста за firstName.В настоящее время я реализовал это так, и это работает:

public DoubleStream getAverageAgesPerFirstName(List<Person> people) {
    return people
            .stream()
            .collect(
                    groupingBy(Person::getFirstName)
            )
            .entrySet()
            .stream()
            .collect(
                    toMap(Entry::getKey, this::getAverageAge)
            )
            .values()
            .stream()
            .mapToDouble(Double::doubleValue)
}

private double getAverageAge(Entry<String, List<Person>> entry) {
        return entry.getValue().stream().map(Person::getAge).mapToDouble(Integer::doubleValue).average().orElse(0);
    }

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

Ответы [ 2 ]

0 голосов
/ 19 октября 2018

Используйте нисходящий коллектор для применения дальнейших операций при группировке, например:

return people.stream()
             .collect(Collectors.collectingAndThen(
                 Collectors.groupingBy(Person::getFirstName, 
                    Collectors.averagingDouble(Person::getAge)), 
                        v -> v.values().stream().mapToDouble(Double::doubleValue));
0 голосов
/ 19 октября 2018

Вот упрощенная версия, в которой используется сборщик averagingDouble:

public DoubleStream getAverageAgesPerFirstName(List<Person> people) {

    return people.stream()
            .collect(Collectors.groupingBy(Person::getFirstName,
                    Collectors.averagingDouble(p -> Double.valueOf(p.getAge()))))
            .values()
            .stream()
            .mapToDouble(d -> d);
}
...