按属性对对象进行分组,并计算每个键的对象属性平均值的组列表

4

假设我有一个Person类:

class Person {
    String firstName;
    String age;

    public String getFirstName() {
        return firstName;
    }

    public String getAge() {
        return age;
    }
}

我有一个List<Person>作为输入。输出时,我想得到每个firstName的平均年龄的DoubleStream。目前我已经实现了以下代码,它可以工作:

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);
    }

我觉得应该有更高效的方法来完成这个任务。最明显的是,在将这些转换为流之前,我正在创建两个中间映射。


你为什么需要一个 DoubleStream?用 double 的平均值不就足够了吗? - Nicholas K
@NicholasK 我需要在其他几个方法中重复使用这个流。 - Robin-Hoodie
2个回答

5

使用下游收集器对分组应用进一步的操作,例如:

return people.stream()
             .collect(Collectors.collectingAndThen(
                 Collectors.groupingBy(Person::getFirstName, 
                    Collectors.averagingDouble(Person::getAge)), 
                        v -> v.values().stream().mapToDouble(Double::doubleValue));

2
这里有一个简化版,使用了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);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接