java stream 原理 flatMap 原理 ,案例Exception分析

case 使用

用来debug学习用 ( 熟悉类图的前提是要了解动态流程,本质的数据流. 类都是为了复用抽象使用的. case越多,使用场景越多, 抽象会越多.)

String[] strings = {"Hello", "World"};
List list = Arrays.asList(strings);

Stream stream = list.stream();
Object collects = stream.map(str -> {
                     return ((String) str).split("");})
                  .flatMap(str-> {
                      return  java.util.Arrays.stream((String[]) str);})
                  .collect(Collectors.toList());
System.out.println(JsonUtils.toJSONString(collects));

输出:

["H","e","l","l","o","W","o","r","l","d"]

stream原理 

stream翻译就是 流 , 有n个pipeline组成 + 一个多线程迭代器Spliterator (splIter Iterator 分割迭代器) . 如下图, list.toStream() ,最终调用如下方法, 生成一个pipeline head.

pipeline家庭

单个pipeline构造方法和重要字段:

1. pipeline head初始化,直接传sourceSpliterator

pipeline head初始化,传sourceSupplier

初始化时,source是自己, sourceSupplier是传过来的 suppiler,提供动态生成 spliterator

构造中间stage pipeline

构造pipeline链

当前的this传递给新的pipeline 即 statelessOp .

pipeline触发

String[] strings = {"Hello", "World"};
List list = Arrays.asList(strings);
Stream stream = list.stream();
Stream stream1 = stream.flatMap(str ->
{
    return ((String) str).split("");
});
Object collects = stream1
        .collect(
                Collectors.toList()
        );
System.out.println(JsonUtils.toJSONString(collects));

封装collector变成,最终层层委托封装给collector

获取源迭代器

封装sink

通过terminalOp(实现类是ReduceOp,ForEachOp,同时也是AccumulatingSink子类)的makeSink接口生成ReducingSink内部类 [其中ReduceOp和ReducingSink都是AccumulatingSink子类,为啥要托管给ReducingSink内部类]

生成sink链(consumer链)

利用pipeline链生成sink链, 将terminalOp的操作,层层传递给下游,从最上游开始执行.

接上图

执行

每个accept都是每个pipeline生成的sink的accept实现. 见上图 flatMap生成的匿名内部类.

抛异常分析

flat直接想转换成List

String[] strings = {"Hello", "World"};
List list = Arrays.asList(strings);
Stream stream = list.stream();
Stream stream1 = stream.flatMap(str ->
{
    return ((String) str).split("");
});
  Object collects = stream1
        .collect(
                Collectors.toList()
        );
System.out.println(JsonUtils.toJSONString(collects));
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.String; cannot be cast to java.util.stream.Stream
	at java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:267)
	at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)

原因是flatmap要求function返回的对象必须是stream.

flatMap其他实例文章

附录:

flatMap时的两个new, 内存代码 和 ddd 领域设计相似点

经验分享 程序员 微信小程序 职场和发展