Java Stream 收集器(四)

上篇是将符合条件的流元素加工后打印出来,这篇讲述如何收集起来。与上篇相比只有最后一个方法不一样

List names= Arrays.asList("one", "two", "three", "four");
List result = names.stream()
                .filter(s -> s.length() > 2)
                .map(String::toUpperCase)
                .collect(Collectors.toList());

Collectors是个工具类,里面有多种方法来实现Collector这个接口:像本例中的Collectors.toList()。

Collectors.java
 //CH_ID 表示流的特性是Collector.Characteristics.IDENTITY_FINISH
public static 
    Collector> toList() {
        return new CollectorImpl<>((Supplier>) ArrayList::new, List::add,
                                   (left, right) -> { left.addAll(right); return left; },CH_ID);
    }

Collector接口提供四个函数,相互配合将输入的条目累加到可变容器中,还能对容器中的结果来一个转化后返回,如果对函数式接口不熟悉,可以参考这篇。

Collector.java
 /**
 *Collector  泛型接口 
 * T 元素类型  本例是String
*  A 归并操作中可累积类型 本例是ArrayList
 * R 归并结束后最终返回类型 本例与A一样
*/
//从名称看就是一个提供者
Supplier supplier();
//从Consumer(消费者)延伸而来,Bi表示两,BiConsumer表示消费两个参数:一个是类型A,一个是类型T 。
BiConsumer accumulator();
//相当于BiFunction 即参数类型和返回类型一样
BinaryOperator combiner();
//Function 表示消费A输出R,也就是对结果转化。本例返回类型R和A一样
Function finisher();

CollectorImpl是Collectors的内部类,实现了Collector接口,比较简单,就是用参数初始化了字段,并提供方法获取

Collectors.java
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;
        }
        //本例使用这个构造方法,如上所说返回类型R和容器类型A一样,因为是泛型,用castingIdentity()方法强转了一下
        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;
        }
       ...
    }

再看collect方法的调用,它是在map方法返回的stream2上调用的

ReferencePipeline.java
public final  R collect(Collector collector) {
        A container;
        if (...) {
            ...
        }
        else {
          //我们是串行流 走这个
            container = evaluate(ReduceOps.makeRef(collector));
        }
        return collector.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)
               ? (R) container  //构造Collector已设置其特性就是IDENTITY_FINISH,所以返回这个
               : collector.finisher().apply(container);
    }

ReduceOps也是一个工具类,这里使用上面的Collector作为参数,创建终结操作的实例

ReduceOps.java
public static  TerminalOp  makeRef(Collector collector) {
        Supplier supplier = Objects.requireNonNull(collector).supplier();
        BiConsumer accumulator = collector.accumulator();
        BinaryOperator combiner = collector.combiner();
        class ReducingSink extends Box  implements AccumulatingSink {
            @Override
            public void begin(long size) {
                state = supplier.get();
            }

            @Override
            public void accept(T t) {
                accumulator.accept(state, t);
            }

            @Override
            public void combine(ReducingSink other) {
                state = combiner.apply(state, other.state);
            }
        }
        return new ReduceOp(StreamShape.REFERENCE) {
            @Override
              //ReduceOp的evaluateSequential方法会调用
            public ReducingSink makeSink() {
                return new ReducingSink();
            }
            ...
        };
    }

先看返回值ReduceOp,它是ReduceOps内部抽象类,实现了TerminalOp。此处返回的是ReduceOp子类,它实现了makesink方法

ReduceOps.java
private static abstract class ReduceOp>
            implements TerminalOp {
        private final StreamShape inputShape;
        ...
      //重要的抽象方法
        public abstract S makeSink();
         ...
        @Override
        public  R evaluateSequential(PipelineHelper helper, Spliterator spliterator) {
          //makeSink()返回ReducingSink
          //和前文一样,helper.wrapAndCopyInto(makeSink(), spliterator)返回makeSink的返回值,即ReducingSink
        // ReducingSink的get方法返回的是ReducingSink中的state,在begin方法中初始化
            return helper.wrapAndCopyInto(makeSink(), spliterator).get();
        }
        ...
    }

后面的流程和前一篇类似。ReducingSink的accept实现了收集操作

@Override
 public void accept(T t) {
       accumulator.accept(state, t);
  }

流遍历结束以后,就会返回ReducingSink中的state,再回顾collect方法

ReferencePipeline.java
public final  R collect(Collector collector) {
        A container;
        if (...) {
            ...
        }
        else {
          //返回的是collector中supplier提供 的内容
            container = evaluate(ReduceOps.makeRef(collector));
        }
        return collector.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)
               ? (R) container  //构造Collector已设置其特性就是IDENTITY_FINISH,所以返回这个,返回类型和容器类型一致
               : collector.finisher().apply(container);
    }

全部流程


Java Stream_collect.png

你可能感兴趣的:(Java Stream 收集器(四))