java8特性:Collectors.groupingBy进行分组、排序等操作 (二)

参考博文

  Stream类的函数

<R, A> R collect(Collector super T, A, R> collector);

可以对数据集进行简单的分组统计。函数参数为接口Collector,其实现在final class Collectors的内部静态类CollectorImpl。Collector接口代码如下:

public interface Collector {

    Supplier supplier();

    BiConsumer accumulator();

    BinaryOperator combiner();

    Function finisher();

    Set characteristics();

    public static Collector of(Supplier supplier,
                                              BiConsumer accumulator,
                                              BinaryOperator combiner,
                                              Characteristics... characteristics) {
        Objects.requireNonNull(supplier);
        Objects.requireNonNull(accumulator);
        Objects.requireNonNull(combiner);
        Objects.requireNonNull(characteristics);
        Set cs = (characteristics.length == 0)
                                  ? Collectors.CH_ID
                                  : Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH,
                                                                           characteristics));
        return new Collectors.CollectorImpl<>(supplier, accumulator, combiner, cs);
    }
    public static Collector of(Supplier supplier,
                                                 BiConsumer accumulator,
                                                 BinaryOperator combiner,
                                                 Function finisher,
                                                 Characteristics... characteristics) {
        Objects.requireNonNull(supplier);
        Objects.requireNonNull(accumulator);
        Objects.requireNonNull(combiner);
        Objects.requireNonNull(finisher);
        Objects.requireNonNull(characteristics);
        Set cs = Collectors.CH_NOID;
        if (characteristics.length > 0) {
            cs = EnumSet.noneOf(Characteristics.class);
            Collections.addAll(cs, characteristics);
            cs = Collections.unmodifiableSet(cs);
        }
        return new Collectors.CollectorImpl<>(supplier, accumulator, combiner, finisher, cs);
    }
    enum Characteristics {
        CONCURRENT,
        UNORDERED,
        IDENTITY_FINISH
    }

}

Collectors

  Collectors中静态内部类实现了Collector接口,并且提供了诸如求最大值、最小值、平均值及求和等函数,可以搭配groupingBy(XXX)使用对数据集进行分组,相关函数及使用示例如下:

1. Collectors.summingInt(XXX)

  summingInt源码:
  


    /**
     * 静态函数
     * 返回一个Collector接口,其可用于产生输入元素‘int型和’的函数
     *
     * @param  输入元素类型
     * @param mapper 函数,抽出需要汇总值得属性
     * @return Collector ,用于产生'驱动属性'的和
     */
    public static  Collector
    summingInt(ToIntFunctionsuper T> mapper) {
        return new Collectors.CollectorImpl<>(
                () -> new int[1],//Supplier === T get();
                (a, t) -> { a[0] += mapper.applyAsInt(t); },//BiConsumer === void accept(T t, U u)
                (a, b) -> { a[0] += b[0]; return a; },// BinaryOperator ===  R apply(T t, U u)
                a -> a[0], // Function === R apply(T t);
                CH_NOID);// Set == int size();
    }

参数ToIntFunction类源码

@FunctionalInterface
public interface ToIntFunction {

    /**
     * Applies this function to the given argument.
     *
     * @param value 函数参数
     */
    int applyAsInt(T value);
}

返回值类所继承的接口Collector

/*
 * 包含
 *    1.返回值为函数类接口的抽象方法;
 *    2.of方法返回其对象实例;
 *    3.枚举类,包含
 *       CONCURRENT,UNORDERED,IDENTITY_FINISH三个元素
 */
public interface Collector {

    Supplier supplier();

    BiConsumer accumulator();

    BinaryOperator combiner();

    Function finisher();

    Set characteristics();

    /* 参数同其方法返回值类型
     * 用给的三个函数类接口实例初始化Collector接口继承类Collectors.CollectorImpl实例,并返回
     */
    public static Collector of(Supplier supplier,
                                              BiConsumer accumulator,
                                              BinaryOperator combiner,
                                              Characteristics... characteristics) {
        Objects.requireNonNull(supplier);//保证函数类接口不为null,否则抛运行时异常
        Objects.requireNonNull(accumulator);//同上
        Objects.requireNonNull(combiner);//同上
        Objects.requireNonNull(characteristics);//同上
        Set cs = (characteristics.length == 0)
                                  ? Collectors.CH_ID
                                  : Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH,
                                                                           characteristics));
        return new Collectors.CollectorImpl<>(supplier, accumulator, combiner, cs);
    }

    /*
     * 用给的三个函数类接口实例初始化Collector接口继承类Collectors.CollectorImpl实例,并返回
     */
    public static Collector of(Supplier supplier,
                                                 BiConsumer accumulator,
                                                 BinaryOperator combiner,
                                                 Function finisher,
                                                 Characteristics... characteristics) {
        Objects.requireNonNull(supplier);
        Objects.requireNonNull(accumulator);
        Objects.requireNonNull(combiner);
        Objects.requireNonNull(finisher);
        Objects.requireNonNull(characteristics);
        Set cs = Collectors.CH_NOID;
        if (characteristics.length > 0) {
            cs = EnumSet.noneOf(Characteristics.class);
            Collections.addAll(cs, characteristics);
            cs = Collections.unmodifiableSet(cs);
        }
        return new Collectors.CollectorImpl<>(supplier, accumulator, combiner, finisher, cs);
    }

    enum Characteristics {

        CONCURRENT,

        UNORDERED,

        IDENTITY_FINISH
    }
}

Collectors.CollectorImpl,静态内部类

   /**
     * Simple implementation class for {@code Collector}.
     *   1.包含几个final变量,类型同继承接口Collector构造器参数,也同其抽象方法返回值;
     *   2.两个构造器,实现方式与Collector类似;
     *   3.重载的父类方法,用其变量赋值;
     */
    static class CollectorImpl implements Collector {
        private final Supplier supplier;
        private final BiConsumer accumulator;
        private final BinaryOperator combiner;
        private final Function finisher;
        private final Set characteristics;

        CollectorImpl(Supplier supplier,
                      BiConsumer accumulator,
                      BinaryOperator combiner,
                      Function finisher,
                      Set characteristics) {
            this.supplier = supplier;
            this.accumulator = accumulator;
            this.combiner = combiner;
            this.finisher = finisher;
            this.characteristics = characteristics;
        }

        CollectorImpl(Supplier supplier,
                      BiConsumer accumulator,
                      BinaryOperator combiner,
                      Set characteristics) {
            this(supplier, accumulator, combiner, castingIdentity(), characteristics);
        }

        @Override
        public BiConsumer accumulator() {
            return accumulator;
        }

        @Override
        public Supplier supplier() {
            return supplier;
        }

        @Override
        public BinaryOperator combiner() {
            return combiner;
        }

        @Override
        public Function finisher() {
            return finisher;
        }

        @Override
        public Set characteristics() {
            return characteristics;
        }
    }

TODO放一段求平均数和求和的函数代码,完全看不懂底层实现

  /**
   *求平均数
   */
    public static  Collector
    averagingInt(ToIntFunctionsuper T> mapper) {
        return new Collectors.CollectorImpl<>(
                () -> new long[2],
                (a, t) -> { a[0] += mapper.applyAsInt(t); a[1]++; },
                (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; },
                a -> (a[1] == 0) ? 0.0d : (double) a[0] / a[1],
                CH_NOID);
    }

 /**
   *求和
   */
    public static  Collector
    summingInt(ToIntFunctionsuper T> mapper) {
        return new Collectors.CollectorImpl<>(
                () -> new int[1],
                (a, t) -> { a[0] += mapper.applyAsInt(t); },
                (a, b) -> { a[0] += b[0]; return a; },
                a -> a[0], CH_NOID);
    }

你可能感兴趣的:(java,函数式编程)