常用的流操作
在深入原理之前丈牢,我們有必要知道關(guān)于Stream的一些基礎(chǔ)知識(shí)瞄沙,關(guān)于Stream的操作分類,如表1-1所示距境。
表1-1 Stream的常用操作分類(表格引自這里)
如表1-1中所示,Stream中的操作可以分為兩大類:中間操作與結(jié)束操作师幕,中間操作只是對(duì)操作進(jìn)行了記錄诬滩,只有結(jié)束操作才會(huì)觸發(fā)實(shí)際的計(jì)算(即惰性求值),這也是Stream在迭代大集合時(shí)高效的原因之一疼鸟。中間操作又可以分為無狀態(tài)(Stateless)操作與有狀態(tài)(Stateful)操作,前者是指元素的處理不受之前元素的影響空镜;后者是指該操作只有拿到所有元素之后才能繼續(xù)下去。結(jié)束操作又可以分為短路與非短路操作张抄,這個(gè)應(yīng)該很好理解洼怔,前者是指遇到某些符合條件的元素就可以得到最終結(jié)果署惯;而后者是指必須處理所有元素才能得到最終結(jié)果镣隶。
源碼解讀
最基礎(chǔ)類對(duì)應(yīng)有ReferencePipeline以及終結(jié)操作對(duì)應(yīng)的ops(例如forEach對(duì)應(yīng)的是ForEachOps),請(qǐng)求有大體分為兩種SHORT_CIRCUIT和非SHORT_CIRCUIT怀酷,非SHORT_CIRCUIT表示請(qǐng)求會(huì)依次得到sink處理,SHORT_CIRCUIT表示請(qǐng)求可能會(huì)中斷蜕依,只處理其中某些因子。對(duì)于鏈?zhǔn)教幚頃?huì)將所有的鏈依次生成對(duì)應(yīng)的sink鏈样眠,后續(xù)會(huì)介紹
打個(gè)比方stream1.filter(predicate1).filter(predicate2).forEach(consumer1);
首先會(huì)調(diào)用ReferencePipeline的filter,生成StatelessOp的op辫秧,主要可以關(guān)注opWrapSink方法被丧,然再次調(diào)用filter生成職責(zé)鏈,通過previousStage進(jìn)行串接甥桂,類似于生成了opForPredicate2 ->opForPredicate1,然后調(diào)用終結(jié)函數(shù)forEach,通過ForEachOps生成ForEachOp的終結(jié)sink黄选,然后調(diào)用FroEachOp的evaluateSequential進(jìn)行請(qǐng)求處理,然后就是訪問者模式相互訪問來去貌夕,看源碼的時(shí)候關(guān)心點(diǎn)放在如下圖:
wrapSink就是為了將最后的consumer通過前面介紹的sinkChain進(jìn)行包裝民镜,生成opForPredicate1Sink->opForPredicate2Sink->consumerAction.
然后通過是否為short_circuit進(jìn)行不同處理,非short_circuit表示所有的屬性都要進(jìn)行操作殃恒,否則表示要進(jìn)行篩選終結(jié)辱揭。
非short_circuit如下:
比如數(shù)組的,獲取每個(gè)數(shù)組元素亥鬓,進(jìn)行action.accept域庇,其中accept就是上面講解的sinkChain.
short_circuit如下:
以limit為例子嵌戈,先電泳forEachWithCancel听皿,首先判斷sink是或否需要取消請(qǐng)求,sliceOp對(duì)應(yīng)的opWrapSink會(huì)維護(hù)一個(gè)m尉姨,每次處理一個(gè)請(qǐng)求就會(huì)減一。當(dāng)為0 的時(shí)候就結(jié)束循環(huán)九府。
最后,對(duì)于stream1.filter(predicate1).limit(1).filter(predicate2).forEach(consumer1);
解析為:生成predicate1Sink->sliceOpSink(m=1)->predicate2Sink->consumer1Action,
依次遍歷stream1中的元素(stream1對(duì)應(yīng)的spliterator的tryAdvance方法)肺蔚,然后判斷sinkChain是否需要cancelRequest(predicate1->sliceOpSink->predicate2Sink),如果需要處理儡羔,則調(diào)用spliterator的tryAdvance執(zhí)行sinkChain