内部类和lambda表达式之间的关系
示例
结论: lambda表达式虽然是匿名内部类的替代品其实两者有本质区别。
- 匿名内部类: 在类里面开辟新的作用域与外层作用域不相同
- lambda : 在类里面没有开辟新的作用域与外层作用域相同
/**
- 内部类和lambda表达式之间的关系
- <p>
- 结论: lambda表达式虽然是匿名内部类的替代品
- 其实两者有本质区别。
- 匿名内部类: 在类里面开辟新的作用域与外层作用域不相同
- lambda : 在类里面没有开辟新的作用域与外层作用域相同
*/
public class LambdaTest {
Runnable runnable = () -> System.out.println(this);
/*
表示Runnable的实现类实现了Runnable接口
此时这个类没名字 所以runnable2是匿名内部类
*/
Runnable runnable2 = new Runnable() {
@Override
public void run() {
//所有此时的this表示的是当前的
// LambdaTest$1匿名内部类对象
System.out.println(this);
}
};
public static void main(String[] args) {
LambdaTest lambdaTest = new LambdaTest();
Thread thread1 = new Thread(lambdaTest.runnable);
thread1.start();
System.out.println("========");
Thread thread2 = new Thread(lambdaTest.runnable2);
thread2.start();
}
}
/**
* ========
* com.shengsiyuan.jdk8.Stream2.LambdaTest@57f64e55 //表示当前类的对象
* com.shengsiyuan.jdk8.Stream2.LambdaTest$1@776d8031 //表示的当前的匿名内部类
*/
TerminalOp
doc
- 流管道中以流为输入并产生结果或副作用的操作。TerminalOp具有输入类型、流形状和结果类型。TerminalOp还具有一组操作标志,用于描述操作如何处理流的元素(例如短路或遵守相遇顺序;请参阅StreamOpFlag)。
- TerminalOp必须提供相对于给定流源和一组中间操作的操作的串行和并行实现。
/*
并行
*/
default <P_IN> R evaluateParallel(PipelineHelper<E_IN> helper,
Spliterator<P_IN> spliterator) {
if (Tripwire.ENABLED)
Tripwire.trip(getClass(), "{0} triggering TerminalOp.evaluateParallel serial default");
//调用串行
return evaluateSequential(helper, spliterator);
}
/**串行
使用指定的PipelineHelper对操作执行顺序求值,后者描述上游中间操作。
*
* @param helper 辅助类 详情看doc
* @param 源分隔迭代器
* @return 评估结果
*/
<P_IN> R evaluateSequential(PipelineHelper<E_IN> helper,
Spliterator<P_IN> spliterator);
}
示例 分析执行流程
public class StreamTest3 {
public static void main(String[] args) {
List<String> list = Arrays.asList("nihao", "hello", "你好");
System.out.println("=====");
Stream<String> stream = list.stream();
System.out.println("1111");
Stream<String> stream2 = stream.map(x -> x + "_abc");
System.out.println("2222");
Stream<String> stringStream = stream2.filter(x -> true);
System.out.println("3333");
stringStream.forEach(System.out::println);
}
源头与中间操作层次体系
如图
终止操作层次体系
终止操作forEach(重要)
为啥惰性操作遇到终止操作会被执行?
底层在调用时会通过wrapSink方法将所有的的中间操作和终止操作包装成一个sink接收器再通过
copyInto方法去执行
sourceSpliterator(terminalOp.getOpFlags())
获取管道源分隔迭代器
约束流元素的执行顺序
因为for循环不返回值所以返回一个null
此时的sink只是存储是终止sink,
遍历第一次完 ,此时当前是filter匿名内部类的第一个opWrapSink方法 下游是终止操作
再遍历 此时是map阶段此时下游是filter阶段 此时返回的sink终止操作已经跟中间操作串联了
此时底层拿到迭代器的数据去遍历包装sink中间操作的每个opWrapSink的返回的匿名内部类的accept方法
AbstractPipeline.sourceSpliterator
doc
获取此管道阶段的源的分隔迭代器。对于串行或无状态并行管道,这是源阶段传过来的分隔迭代器。对于有状态并行管道,返回描述所有计算的结果,包括最新的有状态操作的分隔迭代器。
private Spliterator<?> sourceSpliterator(int terminalFlags) {
// 获取管道的源拆分器
Spliterator<?> spliterator = null;
if (sourceStage.sourceSpliterator != null) {
//如果源分隔迭代器不为空赋值给成员变量spliterator
spliterator = sourceStage.sourceSpliterator;
sourceStage.sourceSpliterator = null;
}
//sourceSpliterator 和sourceSupplier 总一空一有值
else if (sourceStage.sourceSupplier != null) {
//如果源分隔迭代器不为空赋值给成员变量spliterator
spliterator = (Spliterator<?>) sourceStage.sourceSupplier.get();
sourceStage.sourceSupplier = null;
}
else {
throw new IllegalStateException(MSG_CONSUMED);
}
//并行操作 返回源迭代器
if (isParallel() && sourceStage.sourceAnyStateful) {
// Adapt the source spliterator, evaluating each stateful op
// in the pipeline up to and including this pipeline stage.
// The depth and flags of each pipeline stage are adjusted accordingly.
int depth = 1;
for (@SuppressWarnings("rawtypes") AbstractPipeline u = sourceStage, p = sourceStage.nextStage, e = this;
u != e;
u = p, p = p.nextStage) {
int thisOpFlags = p.sourceOrOpFlags;
if (p.opIsStateful()) {
depth = 0;
if (StreamOpFlag.SHORT_CIRCUIT.isKnown(thisOpFlags)) {
// Clear the short circuit flag for next pipeline stage
// This stage encapsulates short-circuiting, the next
// stage may not have any short-circuit operations, and
// if so spliterator.forEachRemaining should be used
// for traversal
thisOpFlags = thisOpFlags & ~StreamOpFlag.IS_SHORT_CIRCUIT;
}
spliterator = p.opEvaluateParallelLazy(u, spliterator);
// Inject or clear SIZED on the source pipeline stage
// based on the stage's spliterator
thisOpFlags = spliterator.hasCharacteristics(Spliterator.SIZED)
? (thisOpFlags & ~StreamOpFlag.NOT_SIZED) | StreamOpFlag.IS_SIZED
: (thisOpFlags & ~StreamOpFlag.IS_SIZED) | StreamOpFlag.NOT_SIZED;
}
p.depth = depth++;
p.combinedFlags = StreamOpFlag.combineOpFlags(thisOpFlags, u.combinedFlags);
}
}
if (terminalFlags != 0) {
// Apply flags from the terminal operation to last pipeline stage
combinedFlags = StreamOpFlag.combineOpFlags(terminalFlags, combinedFlags);
}
return spliterator;
}
PipelineHelper
描述流管道各种各样的信息
doc
- 用于执行流管道的辅助类,在一个位置捕获有关流管道的所有信息(输出类型、中间操作、流标志、并行性等)。
- PipelineHelper描述流管道的初始段,包括它的源操作、中间操作,并且可以另外合并关于终止(或有状态)操作的信息,该终止(或有状态)操作跟随此PipelineHelper描述的最后一个中间操作。PipelineHelper传递给计算平行终止(PipelineHelper,拆分器),终端评估序列(PipelineHelper、拆分器)和AbstractPipeline.OpeValueParallel公司(PipelineHelper、Spliterator、IntFunction)方法,**这些方法可以使用PipelineHelper访问有关管道的信息,例如头部形状,流标志和大小,**并使用诸如wrapAndCopyInto(Sink,Spliterator)、copyInto(Sink,Spliterator)和wrapSink(Sink)等辅助方法执行管道操作。
/**
将当前PipelineHelper描述的管道阶段(一系列动作)应用于提供的
Spliterator<P_IN> spliterator迭代器(里面存放了元素数据),
并将结果发送到提供的S sink接收器。
(意思就是将行为应用到数据上,把结果赋值到Sink上)
*
* @implSpec
* The implementation behaves as if:
* <pre>{@code
* intoWrapped(wrapSink(sink), spliterator);
* }</pre>
*
* @param 接收结果的接收器
* @param 分隔迭代器描述要处理的源输入的分隔迭代器
*/
abstract<P_IN, S extends Sink<P_OUT>> S wrapAndCopyInto(S sink, Spliterator<P_IN> spliterator);
/**
接受PipelineHelper的输出(P_OUT参数)类型的元素的接收器,
并用接受输入(P_IN)类型的元素并实现当前PipelineHelper描述的所有中间操作的接收器
将结果传递到提供的Sink<P_OUT> sink接收器中。
(完成了所有中间操作的一种串联)
*
* @param sink–接收结果的sink
* @return 实现管道阶段并将结果发送到所提供接收器的接收器(谁调用的返回给谁)
*/
abstract<P_IN> Sink<P_IN> wrapSink(Sink<P_OUT> sink);
/**
将从分隔迭代器获得的元素推入提供的水槽Sink<P_IN> wrappedSink当中。
如果已知管道中存在短路阶段(见StreamOpFlag.SHORT_电路),
和已请求接收器取消在每个元素之后检查(),如果请求取消,则停止。
*
此方法符合调用水槽.开始在推动元素之前,
通过接收器。接受,并呼叫水槽末端在所有的元素都被推动之后。
*
* @param 包装后的Sink(此时已经执行所有中间操作){@code Sink}
* @param 源{@code Spliterator}
*/
abstract<P_IN> void copyInto(Sink<P_IN> wrappedSink, Spliterator<P_IN> spliterator);
AbstarctPipeline.wrapAndCopyInto 实现
@Override
final <P_IN, S extends Sink<E_OUT>> S wrapAndCopyInto(S sink, Spliterator<P_IN> spliterator) {
//将迭代器的元素每个元素推送到包装后的接收器里的所有中间操作的行为
copyInto(wrapSink(Objects.requireNonNull(sink)), spliterator);
return sink;
}
@Override
final <P_IN> void copyInto(Sink<P_IN> wrappedSink, Spliterator<P_IN> spliterator) {
Objects.requireNonNull(wrappedSink);
//判断是否包含短路
if (!StreamOpFlag.SHORT_CIRCUIT.isKnown(getStreamAndOpFlags())) {
//sink的执行规则 begin 和 end 方法由子类自行提供
wrappedSink.begin(spliterator.getExactSizeIfKnown());
//wrappedSink 所有中间操作包括终止操作行为封装成一个对象
//每个元素去执行包装sink对象中每个中间操作对应重新的accept 方法
//自上而下执行 map->filter
spliterator.forEachRemaining(wrappedSink);
wrappedSink.end();
}
else {
copyIntoWithCancel(wrappedSink, spliterator);
}
}
AbstarctPipeline.wrapSink(重要)
(完成了所有中间操作的一种串联)doc见PipelineHelper
@Override
@SuppressWarnings("unchecked")
final <P_IN> Sink<P_IN> wrapSink(Sink<E_OUT> sink) {
Objects.requireNonNull(sink);
/*
当p = 源管道 此时 depth 中间操作就等于0了 循环就结束了
for(当前抽象管道;中间操作数>0;赋值p=上游管道){
sink = 当前管道.opWrapSink(执行行为,结果sink)
}
return 包装完毕的sink对象
*/
for ( @SuppressWarnings("rawtypes") AbstractPipeline p=AbstractPipeline.this; p.depth > 0; p=p.previousStage) {
/*使用当前官当执行当前管道之前的包括自己的行为 得到结果赋值给参数sink
opWrapSink的实现其实都在map filter 中间操作中实现了
当循环开始 该方法不停地从后到前去执行中间方法opWrapSink 将终止操作接收的封装了元素
的接收器传递过去并将其串联起来*/
sink = p.opWrapSink(p.previousStage.combinedFlags, sink);
}
return (Sink<P_IN>) sink;
}