91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

學習Java8的Stream

發布時間:2020-07-06 12:38:22 來源:網絡 閱讀:451 作者:superpopb2b 欄目:編程語言

??Stream把對一個集合的很多操作,以一種流式作業串起來,按照類似函數式編程書寫代碼,界面清爽清晰。
??Stream不同于Guava的FluentIterable系列。FluentIterable系列,是通過封裝集合(List、Set等)并且重載迭代器、get的方式,進行的transform、filter等,優點是簡單并且性能高。缺點是功能單一、并且容易誤用。比如,對transform之后的列表的每個項,本質上都是一個視圖(View),而不是實際的項(值對象)。多次調用get方法。這本質上每次都會層層調用Function的apply方法,如果其中有復雜運算或者I/O讀取,效率是非常低的。
  Stream本身,建立了一系列的數據結構,其中的數據都可以看成是實際存在的數據,而并不僅僅是視圖。網上分析源代碼的文章非常多,這里不重復描述,而是僅僅介紹理解的一個思路。
??首先,是幾個關鍵的數據結構。
??Stream。接口是BaseStream,可以看做是流基本『形態』的描述。或者說,每個流式作業。雖然后面提到的Pipeline也是實現了BaseStream,但是這樣似乎更容易理解。
??Pipeline。公共父類是AbstractPipeline。可以看做是流式作業中的每個作業,或者說是每個作業節點。為了防止不必要的裝箱和拆箱操作,又分成了ReferencePipeline、IntPipeline、LongPipeline、DoublePipeline。這些管道可以分成三種:頭、終結操作、非終結操作。分別對應的類是XXXXPipeline.Head、XXXXPipeline.StatelessOp和XXXXPipeline.StatefulOp、TerminalOp.調用流的工作方法,都會制造出來這樣一個Pipeline。比如,調用IntStream.of(),就會生成一個頭;調用Stream.map(),會生成一個非終結操作;調用Stream.reduce(),生成一個終結操作。非終結操作里面,都要實現opWrapSink方法,該方法要返回一個Sink。
??Sink。每個操作,對應一個Sink。每個Sink,關注三個方法:begin、end、accept。如果當前的Sink沒有操作,那么直接調用downstream.accept;否則,把當前操作結果作為參數調用downstream.accept。downstream是什么概念呢?比如,一個流的操作是IntStream.of(1,2,3).map(x -> x + 1).boxed().max()。那么map對應的sink,就是頭的downstream,boxed對應的sink就是map的downstream。綜合起來,只要調用了頭的accept,就會層層調用到最后一個終結操作。終結操作沒有opWrapSink方法,所以自然不會調用到后續的流。
??Spliterator。流里面數據的訪問工具。如果是串行流,一般是直接調用里面的forEachRemaining。該方法里關注action.accept,如果之前串聯好了每個Sink,那么這里一句調用,就開始了Sink的層層調用。
??至此,基本數據結構就介紹這些。下面,關注流的每個節點,是如何連起來的。
??每個Stream,由一組Pipeline節點組成,每追加一個操作,都會向這組Pipeline后面追加一個Pipeline結構。追加時候維護的信息里面,關注sourceStage(頭),previousStage(上一個Pipeline),sourceSupplier(流數據的Spliterator),depth(Pipeline長度)。一直到最后的終結操作,連城一個Pipeline鏈。
??對于終結操作,不論是reduce,還是collect操作,都會調用到AbstracePipeline.evaluate方法。以串行流的reduce為例,直接調用到AbstractPipeline.wrapAndCopyInto。
??其中,wrap是遍歷Pipeline鏈,調用每個階段的opWrapSink。這樣每個Sink通過方法逐層調用(而非內存數據上的指針鏈接),從第一個Pipeline的Sink鏈接到末尾。

    @Override
    @SuppressWarnings("unchecked")
    final <P_IN> Sink<P_IN> wrapSink(Sink<E_OUT> sink) {
        Objects.requireNonNull(sink);

        for ( @SuppressWarnings("rawtypes") AbstractPipeline p=AbstractPipeline.this; p.depth > 0; p=p.previousStage) {
            sink = p.opWrapSink(p.previousStage.combinedFlags, sink);
        }
        return (Sink<P_IN>) sink;
    }

??copyInto是依次調用Sink.begin,Spliterator.forEachRemaing,Sink.end方法。上文曾經提到,forEachRemaing會以流里的每項數據為參數,層層調用每級Sink的accept。

    @Override
    final <P_IN> void copyInto(Sink<P_IN> wrappedSink, Spliterator<P_IN> spliterator) {
        Objects.requireNonNull(wrappedSink);

        if (!StreamOpFlag.SHORT_CIRCUIT.isKnown(getStreamAndOpFlags())) {
            wrappedSink.begin(spliterator.getExactSizeIfKnown());
            spliterator.forEachRemaining(wrappedSink);
            wrappedSink.end();
        }
        else {
            copyIntoWithCancel(wrappedSink, spliterator);
        }
    }

??至此,整個流的操作,自上而下完全聯系到了一起。
??

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

西宁市| 清镇市| 肃宁县| 普安县| 武安市| 筠连县| 桑植县| 青田县| 常德市| 梁山县| 嘉义县| 汪清县| 新丰县| 西充县| 白城市| 教育| 鹤庆县| 凤凰县| 奉新县| 苏州市| 平昌县| 博罗县| 封开县| 镶黄旗| 朔州市| 离岛区| 清丰县| 宁武县| 仲巴县| 惠水县| 虞城县| 上饶县| 客服| 夏河县| 花垣县| 夏津县| 平阳县| 靖远县| 施甸县| 呼玛县| 三原县|