lambda表達式:終止操作執行流程重要方法分析 PipelineHelper源碼解析

內部類和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);
}

終止操作forEach(重要)

爲啥惰性操作遇到終止操作會被執行?

底層在調用時會通過wrapSink方法將所有的的中間操作和終止操作包裝成一個sink接收器再通過
copyInto方法去執行

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

sourceSpliterator(terminalOp.getOpFlags())

獲取管道源分隔迭代器在這裏插入圖片描述
約束流元素的執行順序
在這裏插入圖片描述
在這裏插入圖片描述
因爲for循環不返回值所以返回一個null
在這裏插入圖片描述
在這裏插入圖片描述

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 方法 
            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; 
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章