Java Stream match操作(五)

Stream Head的構(gòu)建(一)
Stream 的中間操作(二)
Stream的終止操作(三)
本篇講述match操作娃闲,省略中間流操作,有以下三種方式骑晶,方法名已經(jīng)說明的其功能

List<String> names= Arrays.asList("one", "two", "three", "four");
boolean anyMatch = names.stream().anyMatch(s -> s.length()>2);
boolean allMatch = names.stream().allMatch(s -> s.length()<10);
boolean noneMatch = names.stream().noneMatch(s -> s.length()!=5);

從源碼看,調(diào)用的方法相同刺桃,只是參數(shù)不一樣步清,下文會分析其意義

ReferencePipeline.java
 @Override
    public final boolean anyMatch(Predicate<? super P_OUT> predicate) {
        return evaluate(MatchOps.makeRef(predicate, MatchOps.MatchKind.ANY));
    }

    @Override
    public final boolean allMatch(Predicate<? super P_OUT> predicate) {
        return evaluate(MatchOps.makeRef(predicate, MatchOps.MatchKind.ALL));
    }

    @Override
    public final boolean noneMatch(Predicate<? super P_OUT> predicate) {
        return evaluate(MatchOps.makeRef(predicate, MatchOps.MatchKind.NONE));
    }

終止操作構(gòu)建的套路差不多

MatchOps.java
public static <T> TerminalOp<T, Boolean> makeRef(Predicate<? super T> predicate,
            MatchKind matchKind) {
        Objects.requireNonNull(predicate);
        Objects.requireNonNull(matchKind);
        //先忽略
        class MatchSink extends BooleanTerminalSink<T> {
            MatchSink() {
                super(matchKind);
            }
            @Override
            public void accept(T t) {
                if (!stop && predicate.test(t) == matchKind.stopOnPredicateMatches) {
                    stop = true;
                    value = matchKind.shortCircuitResult;
                }
            }
        }
        return new MatchOp<>(StreamShape.REFERENCE, matchKind, MatchSink::new);
    }

這里使用構(gòu)造函數(shù)的方法引用實例化Supplier<BooleanTerminalSink<T>>接口,sinkSupplier.get()的調(diào)用才會真正new對象虏肾。不熟悉可以參考這篇廓啊。

private static final class MatchOp<T> implements TerminalOp<T, Boolean> {
        private final StreamShape inputShape;
        final MatchKind matchKind;
        final Supplier<BooleanTerminalSink<T>> sinkSupplier;
               MatchOp(StreamShape shape,
                MatchKind matchKind,
                Supplier<BooleanTerminalSink<T>> sinkSupplier) {
            this.inputShape = shape;
            this.matchKind = matchKind;
            this.sinkSupplier = sinkSupplier;
        }
        @Override
        public int getOpFlags() {
            注意操作標(biāo)記是短路的,表示流元素可能發(fā)了一部分就被叫停了封豪。后面會用到
            return StreamOpFlag.IS_SHORT_CIRCUIT | StreamOpFlag.NOT_ORDERED;
        }
        ...
        @Override
        public <S> Boolean evaluateSequential(PipelineHelper<T> helper,
                                              Spliterator<S> spliterator) {
            return helper.wrapAndCopyInto(sinkSupplier.get(), spliterator).getAndClearState();
        }
       ...
    }

在wrapAndCopyInto之前谴轮,需要講一下MatchKind,有三個枚舉類型ANY吹埠、ALL第步、NONE,意義如下

enum MatchKind {
         找一個符合條件的缘琅,短路返回true 
        ANY(true, true),

        找到一個不合法條件的粘都,短路返回false 
        ALL(false, false),

        找到一個符合條件的,短路返回false 
        NONE(true, false);
        對判斷結(jié)果的期望刷袍,any期望true翩隧,all期望false,none期望true呻纹,一旦期望成真即短路
        private final boolean stopOnPredicateMatches;
        發(fā)生短路返回的值
        private final boolean shortCircuitResult;

        private MatchKind(boolean stopOnPredicateMatches,boolean shortCircuitResult) {
            this.stopOnPredicateMatches = stopOnPredicateMatches;
            this.shortCircuitResult = shortCircuitResult;
        }
    }

MatchSink使用MatchKind作為參數(shù)調(diào)用父類BooleanTerminalSink初始化返回值value堆生,對短路結(jié)果取反

private static abstract class BooleanTerminalSink<T> implements Sink<T> {
        boolean stop;
        boolean value;

        BooleanTerminalSink(MatchKind matchKind) {
            value = !matchKind.shortCircuitResult;
        }

        public boolean getAndClearState() {
            return value;
        }

        @Override
        public boolean cancellationRequested() {
            return stop;
        }
    }

和以前一樣來到這里,不同的是這次標(biāo)記是SHORT_CIRCUIT

AbstractPipeline
 @Override
    final <P_IN> void copyInto(Sink<P_IN> wrappedSink, Spliterator<P_IN> spliterator) {
        Objects.requireNonNull(wrappedSink);
        if (!StreamOpFlag.SHORT_CIRCUIT.isKnown(getStreamAndOpFlags())) {
            ...
        }
        else {
            //有短路操作
            copyIntoWithCancel(wrappedSink, spliterator);
        }
    }


 final <P_IN> void copyIntoWithCancel(Sink<P_IN> wrappedSink, Spliterator<P_IN> spliterator) {
        @SuppressWarnings({"rawtypes","unchecked"})
        AbstractPipeline p = AbstractPipeline.this;
        //回到源頭
        while (p.depth > 0) {
            p = p.previousStage;
        }
        wrappedSink.begin(spliterator.getExactSizeIfKnown());
        p.forEachWithCancel(spliterator, wrappedSink);
        wrappedSink.end();
    }

這里和以前略有不同,我們不需要遍歷整個數(shù)據(jù)源雷酪,只要下游達(dá)到目的就能提前收工淑仆。每發(fā)射一次都有問一下是否繼續(xù)

ReferencePipeline
@Override
    final void forEachWithCancel(Spliterator<P_OUT> spliterator, Sink<P_OUT> sink) {
        do { } while (!sink.cancellationRequested() && spliterator.tryAdvance(sink));
    }

再看看MatchSink對元素的處理,這是整個功能的核心哥力。

@Override
public void accept(T t) {
    開始stop=false蔗怠,判斷式是否符合期望,如前面所述
    ANY-->期望predicate.test(t) 表達(dá)式返回true
    ALL-->期望predicate.test(t) 表達(dá)式返回false
    NONE-->期望predicate.test(t)表達(dá)式返回true
    判斷短小精悍  
    if (!stop && predicate.test(t) == matchKind.stopOnPredicateMatches) {
        stop = true;
        value = matchKind.shortCircuitResult;
    }
}

一旦達(dá)到期望,stop=true寞射,即請求取消最住;重新給value賦值,這是我們達(dá)到期望要返回的值怠惶。如果遍歷到結(jié)束涨缚,說明大失所望,value值就是之前的取反值

private static abstract class BooleanTerminalSink<T> implements Sink<T> {
        boolean stop;
        boolean value;

        BooleanTerminalSink(MatchKind matchKind) {
            value = !matchKind.shortCircuitResult;
        }

        public boolean getAndClearState() {
            return value;
        }

        @Override
        public boolean cancellationRequested() {
            return stop;
        }
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末策治,一起剝皮案震驚了整個濱河市脓魏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌通惫,老刑警劉巖茂翔,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異履腋,居然都是意外死亡珊燎,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門遵湖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來悔政,“玉大人,你說我怎么就攤上這事延旧∧惫” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵迁沫,是天一觀的道長芦瘾。 經(jīng)常有香客問我,道長集畅,這世上最難降的妖魔是什么近弟? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮挺智,結(jié)果婚禮上祷愉,老公的妹妹穿的比我還像新娘。我一直安慰自己逃贝,他們只是感情好谣辞,可當(dāng)我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著沐扳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪句占。 梳的紋絲不亂的頭發(fā)上沪摄,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天,我揣著相機與錄音,去河邊找鬼杨拐。 笑死祈餐,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的哄陶。 我是一名探鬼主播帆阳,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼屋吨!你這毒婦竟也來了蜒谤?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤至扰,失蹤者是張志新(化名)和其女友劉穎鳍徽,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體敢课,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡阶祭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了直秆。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片濒募。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖圾结,靈堂內(nèi)的尸體忽然破棺而出萨咳,到底是詐尸還是另有隱情,我是刑警寧澤疫稿,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布培他,位于F島的核電站,受9級特大地震影響遗座,放射性物質(zhì)發(fā)生泄漏舀凛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一途蒋、第九天 我趴在偏房一處隱蔽的房頂上張望猛遍。 院中可真熱鬧,春花似錦号坡、人聲如沸懊烤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽腌紧。三九已至,卻和暖如春畜隶,著一層夾襖步出監(jiān)牢的瞬間壁肋,已是汗流浹背号胚。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留浸遗,地道東北人猫胁。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像跛锌,于是被迫代替她去往敵國和親弃秆。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內(nèi)容