猿问

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

在上降低甲骨文创新与流提供了如何的人的集合转换成包含基于性别的平均年龄地图的例子。它使用以下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不够的。


慕虎7371278
浏览 228回答 2
2回答

神不在的星期二

仅Collector.of(Supplier, BiConsumer, BinaryOperator, [Function,] Characteristics...)用于这些情况:Collector.of(() -> new double[2],&nbsp; &nbsp; &nbsp; &nbsp; (a, t) -> { a[0] += t.getAge(); a[1]++; },&nbsp; &nbsp; &nbsp; &nbsp; (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; },&nbsp; &nbsp; &nbsp; &nbsp; a -> (a[1] == 0) ? 0.0 : a[0] / a[1]))虽然定义 a 可能更具可读性PersonAverager:class PersonAverager {&nbsp; &nbsp; double sum = 0;&nbsp; &nbsp; int count = 0;&nbsp; &nbsp; void accept(Person p) {&nbsp; &nbsp; &nbsp; &nbsp; sum += p.getAge();&nbsp; &nbsp; &nbsp; &nbsp; count++;&nbsp; &nbsp; }&nbsp; &nbsp; PersonAverager combine(PersonAverager other) {&nbsp; &nbsp; &nbsp; &nbsp; sum += other.sum;&nbsp; &nbsp; &nbsp; &nbsp; count += other.count;&nbsp; &nbsp; &nbsp; &nbsp; return this;&nbsp; &nbsp; }&nbsp; &nbsp; double average() {&nbsp; &nbsp; &nbsp; &nbsp; return count == 0 ? 0 : sum / count;&nbsp; &nbsp; }}并将其用作:Collector.of(PersonAverager::new,&nbsp; &nbsp; &nbsp; &nbsp; PersonAverager::accept,&nbsp; &nbsp; &nbsp; &nbsp; PersonAverager::combine,&nbsp; &nbsp; &nbsp; &nbsp; PersonAverager::average)
随时随地看视频慕课网APP

相关分类

Java
我要回答