为了账号安全,请及时绑定邮箱和手机立即绑定

如何在 groupingBy 操作中使用自定义收集器

如何在 groupingBy 操作中使用自定义收集器

慕虎7371278 2021-10-13 17:34:05
在上降低甲骨文创新与流提供了如何的人的集合转换成包含基于性别的平均年龄地图的例子。它使用以下Person类和代码:public class Person {    private int age;    public enum Sex {        MALE,        FEMALE    }    private Sex sex;    public Person (int age, Sex sex) {        this.age = age;        this.sex = sex;    }    public int getAge() { return this.age; }    public Sex getSex() { return this.sex; }}Map<Person.Sex, Double> averageAgeByGender = roster    .stream()    .collect(        Collectors.groupingBy(            Person::getSex,                                  Collectors.averagingInt(Person::getAge)));上面的流代码效果很好,但我想看看如何在使用收集器的自定义实现时执行相同的操作。我在 Stack Overflow 或网络上都找不到有关如何执行此操作的完整示例。至于我们为什么要这样做,作为一个例子,也许我们想要计算某种涉及年龄的加权平均值。在这种情况下, 的默认行为是Collectors.averagingInt不够的。
查看完整描述

2 回答

?
神不在的星期二

TA贡献1963条经验 获得超6个赞

仅Collector.of(Supplier, BiConsumer, BinaryOperator, [Function,] Characteristics...)用于这些情况:


Collector.of(() -> new double[2],

        (a, t) -> { a[0] += t.getAge(); a[1]++; },

        (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; },

        a -> (a[1] == 0) ? 0.0 : a[0] / a[1])

)

虽然定义 a 可能更具可读性PersonAverager:


class PersonAverager {

    double sum = 0;

    int count = 0;


    void accept(Person p) {

        sum += p.getAge();

        count++;

    }


    PersonAverager combine(PersonAverager other) {

        sum += other.sum;

        count += other.count;

        return this;

    }


    double average() {

        return count == 0 ? 0 : sum / count;

    }

}

并将其用作:


Collector.of(PersonAverager::new,

        PersonAverager::accept,

        PersonAverager::combine,

        PersonAverager::average)


查看完整回答
反对 回复 2021-10-13
  • 2 回答
  • 0 关注
  • 227 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信