1. lambda与匿名内部类区别
出现了lambda表达式和函数式接口后,对于之前的匿名内部类语法,就有了很好的替代方式。使用lambda会使得语法更简单,但是二者本质上还是不同的。
public class LambdaTest {
Runnable r1 = () -> System.out.println(this);
Runnable r2 = new Runnable() {
@Override
public void run() {
System.out.println(this);
}
};
public static void main(String[] args) {
LambdaTest test = new LambdaTest();
Thread t1 = new Thread(test.r1);
Thread t2 = new Thread(test.r2);
t1.start();
t2.start();
}
}
输出结果如下:
stream1.LambdaTest@1f3f7e6a
stream1.LambdaTest$1@9ec32f5
打印出的this有着不同的语义:
第一行的this表示LambdaTest类的一个实例;
第二行的$1, 它表示了LambdaTest类下实现了Runnable接口的一个匿名内部类;
结论: lambda虽然可以和匿名内部类完成相同的功能,但是两者有着本质的区别。lambda不是匿名内部类的语法糖。通过上面的例子可以看出, 他们所处的作用域
是不同的。
2. Stream几个重要的实现类
AbstractPipeline
它是一个抽象类,是Stream接口的核心实现类,管理着流管道(pipline)的构造和计算。它封装了stream的源和0个或多个中间操作。
shape-specific pipeline, 如IntPipline, DoublePipline, LongPipline, ReferencePipeline等等,都继承了AbstractPipline。
它本质上是一个
双向链表
,有着sourceStage,previousStage, nextStage 等属性。因此它可以把流的多个中间操作(称之为阶段stage) 给有序的连接起来。每一个stage 都有着上游(UpStream)或者说下游(DownStream)的概念。
Sink
继承自Consumer接口:
它有两种状态: 初始状态(initial state)和活跃状态(active state)。
begig()方法将其从initial state->active state, 要求在accept()方法之前被调用。
end()方法将其从active state->initial state, 要求在accept()方法之后被调用。
三个方法的执行顺序: begin-> accpet-> end。 这里运用了模板方法模式。
StatelessOp
它表示流无状态的中间阶段的基类。(Base class for a stateless intermediate stage of a Stream.)
该类的继承体系如下图:
![这里写图片描述](https://i-blog.csdnimg.cn/blog_migrate/7f8f29d13667a9856cffb158534a1a3e.png)
它是一个抽象类,重写了AbstractPipeline类的opIsStateful方法,返回了false,表示它是无状态的。
它和ReferencePipeline.Head 在同一个层次,都继承自ReferencePipeline, 一个表示流的源阶段,一个表示流的中间阶段。
ForEachOps
他是用户创建TerminalOp实例的工厂类。TerminalOp是终止操作最顶层的一个接口。TerminalOp接口的实现类有ForEachOp, ReduceOp,FindOp, MatchOp。
总结:AbstractPipline封装了流的源(Head)和中间操作(StatelessOp和 StatefulOp)。
IntPipeline, DoublePipeline, LongPipeline, ReferencePipeline 是平级的,他们都继承自AbstractPipline, 每个类各自定义了Head, StatelessOp和StatefulOp抽象类。