Java8之Stream流(二)關(guān)鍵知識點(diǎn)

Java8之Stream流(一)基礎(chǔ)體驗(yàn)
Java8之Stream流(三)縮減操作
Java8之Stream流(四)并行流
Java8之Stream流(五)映射流
Java8之Stream流(六)收集
Java8之Stream流(七)流與迭代器

我們的第一篇文章役电,主要是通過一個Demo姥饰,讓大家體驗(yàn)了一下使用流API的那種酣暢淋漓的感覺鄙陡。如果你沒有實(shí)踐轰枝,我還是再次呼吁你動手敲一敲碉考,自己實(shí)實(shí)在跑一遍上一篇的Demo导绷。相信你的感受和理解也會隨之加深的累魔。繼續(xù)探索流API的高級功能之前,我們先從接口級別全面了解一下流API副女,這個對于我們來說是至關(guān)重要的蛤高。但這一篇不需要花太多時(shí)間,直接看一遍就可以了碑幅。接下來戴陡,我給大家準(zhǔn)備了一張流API關(guān)鍵知識點(diǎn)的UML圖。但是大家只需要花一兩分鐘沟涨,整理看一下就可以了恤批,不需要記住,先有個印象裹赴,后面我給大家講解一些關(guān)鍵的方法:

流API UML

流API UML

我先整體介紹一下:流API定義的幾個接口喜庞,都是在java.util.stream包中的.其中上圖中的BaseStream接口是最基礎(chǔ)的接口,它提供了所有流都可以使用的基本功能:

public interface BaseStream<T, S extends BaseStream<T, S>> extends AutoCloseable {
//....先忽略這些具體的細(xì)節(jié)
}

由這個接口的定義我們得知棋返,BaseStream是一個泛型接口,它有兩個類型參數(shù)T和S延都, 其中T指定了流中的元素的類型,并且由<S extends BaseStream<T, S>>可以知道S必須為BaseStream或BaseStream子類(換句話說,就是S必須是擴(kuò)展自BaseStream的)。BaseStream繼承了AutoCloseable接口懊昨。這個接口主要是簡化了關(guān)閉資源的操作窄潭。但是像平時(shí)我們操作的集合或數(shù)組春宣,基本上都不會出現(xiàn)關(guān)閉流的情況酵颁。

//由BaseStream接口派生出的流接口包括IntStream ,LongStream月帝,DoubleStream 躏惋,Stream<T>
public interface IntStream extends BaseStream<Integer, IntStream> {
}
public interface LongStream extends BaseStream<Long, LongStream> {
}
public interface DoubleStream extends BaseStream<Double, DoubleStream> {
}

//這是最具代表性的接口
public interface Stream<T> extends BaseStream<T, Stream<T>> {
//....先忽略這些具體的細(xì)節(jié)
}

由于Stream接口是最具代表性的,所以我們就選擇它來講解嚷辅,其實(shí)在我們學(xué)完Stream接口簿姨,其它的三個接口,在使用上基本是一致的了,我們上一篇的Demo基本上也是使用Stream接口來做的練習(xí)扁位。我們回想一下:在上一個Demo中我們通過集合框架的stream()方法准潭,就能返回一個流了,它的返回類型就是Stream<T>域仇,比如我們Stream<Integer>刑然,由此得知,Stream接口里的類型參數(shù)T就是流中的元素的類型暇务。木有錯泼掠,就是這樣滴。到這里垦细,整個系列你們已經(jīng)全部學(xué)會了择镇,下課。


戰(zhàn)斗才剛剛開始括改!


現(xiàn)在是時(shí)候開始記憶一些知識了.

BaseStream詳解:

public interface BaseStream<T, S extends BaseStream<T, S>> extends AutoCloseable {
     Iterator<T> iterator();//line2
     Spliterator<T> spliterator();//line3
     boolean isParallel();//line4
     S sequential();//line5
     S parallel();//line6
     S unordered();//line7
     S onClose(Runnable closeHandler);//line8
     @Override
     void close();//line10
}
  • Iterator<T> iterator(); //line2
    獲得流的迭代器腻豌,并返回對該迭代器的引用(終端操作)
  • Spliterator<T> spliterator(); //line3
    獲取流的spliterator,并返回其引用(終端操作)
  • boolean isParallel(); //line4
    如果調(diào)用流是一個并行流嘱能,則返回true;如果調(diào)用流是一個順序流饲梭,則返回false。
  • S sequential(); //line5
    基于調(diào)用流焰檩,返回一個順序流憔涉。如果調(diào)用流已經(jīng)是順序流了,就返回該流析苫。(中間操作)
  • S parallel(); //line6
    基于調(diào)用流兜叨,返回一個并行流。如果調(diào)用流已經(jīng)是并行流了衩侥,就返回該流国旷。(中間操作)
  • S unordered(); //line7
    基于調(diào)用流,返回一個無序流茫死。如果調(diào)用流已經(jīng)是無序流了跪但,就返回該流。(中間操作)
  • S onClose(Runnable closeHandler); //line8
    返回一個新流峦萎,closeHandler指定了該流的關(guān)閉處理程序屡久,當(dāng)關(guān)閉該流時(shí),將調(diào)用這個處理程序爱榔。(中間操作)
  • void close(); //line10
    從AutoCloseable繼承來的被环,調(diào)用注冊關(guān)閉處理程序,關(guān)閉調(diào)用流(很少會被使用到)

"終端操作"&"中間操作"

細(xì)心的同學(xué)應(yīng)該注意到了详幽,BaseStream接口里面的很多方法都在最后標(biāo)識了(終端操作)和(中間操作)筛欢,它們之間的區(qū)別是非常重要的浸锨。

  • 終端操作 會消費(fèi)流,這種操作會產(chǎn)生一個結(jié)果的版姑,比如上面的 iterator()和 spliterator()柱搜,以及上一篇中提到的min()和max(),或者是執(zhí)行某一種操作剥险,比如上一篇的forEach()冯凹,如果一個流被消費(fèi)過了,那它就不能被重用的炒嘲。

  • 中間操作 中間操作會產(chǎn)生另一個流宇姚。因此中間操作可以用來創(chuàng)建執(zhí)行一系列動作的管道。一個特別需要注意的點(diǎn)是:中間操作不是立即發(fā)生的夫凸。相反浑劳,當(dāng)在中間操作創(chuàng)建的新流上執(zhí)行完終端操作后,中間操作指定的操作才會發(fā)生夭拌。所以中間操作是延遲發(fā)生的魔熏,中間操作的延遲行為主要是讓流API能夠更加高效地執(zhí)行。

"中間操作"的狀態(tài)

流的中間操作鸽扁,可以為分無狀態(tài)操作有狀態(tài)操作兩種蒜绽,在無狀態(tài)操作中,在處理流中的元素時(shí)桶现,會對當(dāng)前的元素進(jìn)行單獨(dú)處理躲雅。比如:謂詞過濾操作,因?yàn)槊總€元素都是被單獨(dú)進(jìn)行處理的骡和,所有它和流中的其它元素?zé)o關(guān)相赁,因此被稱為無狀態(tài)操作;而在有狀態(tài)操作中,某個元素的處理可能依賴于其他元素慰于。比如查找最小值钮科,最大值,和排序婆赠,因?yàn)樗麄兌家蕾囉谄渌脑孛喔R虼藶榉Q為有狀態(tài)操作。當(dāng)需要進(jìn)行并行處理流時(shí)休里,有狀態(tài)的操作和無狀態(tài)的區(qū)別是非常重要的蛆挫,因?yàn)橛袪顟B(tài)操作可能需要幾次處理才能完成,后面的文章我將會給大家詳細(xì)地講份帐,現(xiàn)在只需要正常學(xué)習(xí)下去就可以了

另外璃吧,指出一點(diǎn)楣导,如果大家了解泛型的話废境,應(yīng)該知道,泛型的類型參數(shù)只能是引用類型,因此Stream操作的對象只能是引用類型的噩凹,不能用于基本類型巴元。當(dāng)然官方早已考慮到這一點(diǎn)了,前面你們看到的IntStream驮宴,LongStream逮刨,DoubleStream就是官方給我們提供的處理基本類型的流了。此處是不是應(yīng)該給他們掌聲堵泽!

Stream詳解

在有了前面的那些知識作鋪墊之后修己,學(xué)Stream接口應(yīng)該會順風(fēng)順?biāo)恕_€是先看看Stream的詳情先:

public interface Stream<T> extends BaseStream<T, Stream<T>> {
    Stream<T> filter(Predicate<? super T> predicate);//line2
    <R> Stream<R> map(Function<? super T, ? extends R> mapper);//line3
    IntStream mapToInt(ToIntFunction<? super T> mapper);//line4
    LongStream mapToLong(ToLongFunction<? super T> mapper);
    DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);
    <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
    IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper);
    LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper);
    DoubleStream flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper);
    Stream<T> distinct();
    Stream<T> sorted();//line12
    Stream<T> sorted(Comparator<? super T> comparator);//line13
    Stream<T> peek(Consumer<? super T> action);
    Stream<T> limit(long maxSize);
    Stream<T> skip(long n);
    void forEach(Consumer<? super T> action);//line17
    void forEachOrdered(Consumer<? super T> action);//line18
    Object[] toArray();
    <A> A[] toArray(IntFunction<A[]> generator);
    T reduce(T identity, BinaryOperator<T> accumulator);
    Optional<T> reduce(BinaryOperator<T> accumulator);
    <U> U reduce(U identity,
                 BiFunction<U, ? super T, U> accumulator,
                 BinaryOperator<U> combiner);
    <R> R collect(Supplier<R> supplier,
                  BiConsumer<R, ? super T> accumulator,
                  BiConsumer<R, R> combiner);
    <R, A> R collect(Collector<? super T, A, R> collector);
    Optional<T> min(Comparator<? super T> comparator);//line30
    Optional<T> max(Comparator<? super T> comparator);//line31
    long count();
    boolean anyMatch(Predicate<? super T> predicate);
    boolean allMatch(Predicate<? super T> predicate);
    boolean noneMatch(Predicate<? super T> predicate);
    Optional<T> findFirst();
    Optional<T> findAny();

    // Static factories

    public static<T> Builder<T> builder() {
        return new Streams.StreamBuilderImpl<>();
    }


    public static<T> Stream<T> empty() {
        return StreamSupport.stream(Spliterators.<T>emptySpliterator(), false);
    }


    public static<T> Stream<T> of(T t) {
        return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
    }


    @SafeVarargs
    @SuppressWarnings("varargs") // Creating a stream from an array is safe
    public static<T> Stream<T> of(T... values) {
        return Arrays.stream(values);
    }


    public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) {
        Objects.requireNonNull(f);
        final Iterator<T> iterator = new Iterator<T>() {
            @SuppressWarnings("unchecked")
            T t = (T) Streams.NONE;

            @Override
            public boolean hasNext() {
                return true;
            }

            @Override
            public T next() {
                return t = (t == Streams.NONE) ? seed : f.apply(t);
            }
        };
        return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
                iterator,
                Spliterator.ORDERED | Spliterator.IMMUTABLE), false);
    }


    public static<T> Stream<T> generate(Supplier<T> s) {
        Objects.requireNonNull(s);
        return StreamSupport.stream(
                new StreamSpliterators.InfiniteSupplyingSpliterator.OfRef<>(Long.MAX_VALUE, s), false);
    }


    public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) {
        Objects.requireNonNull(a);
        Objects.requireNonNull(b);

        @SuppressWarnings("unchecked")
        Spliterator<T> split = new Streams.ConcatSpliterator.OfRef<>(
                (Spliterator<T>) a.spliterator(), (Spliterator<T>) b.spliterator());
        Stream<T> stream = StreamSupport.stream(split, a.isParallel() || b.isParallel());
        return stream.onClose(Streams.composedClose(a, b));
    }
}
  • Stream<T> filter(Predicate<? super T> predicate); //line2
    產(chǎn)生一個新流迎罗,其中包含調(diào)用流中滿足predicate指定的謂詞元素(中間操作)
  • <R> Stream<R> map(Function<? super T, ? extends R> mapper); //line3
    產(chǎn)生一個新流睬愤,對調(diào)用流中的元素應(yīng)用mapper,新流中包含這些元素纹安。(中間操作)
  • IntStream mapToInt(ToIntFunction<? super T> mapper); //line4
    對調(diào)用流中元素應(yīng)用mapper尤辱,產(chǎn)生包含這些元素的一個新IntStream流。(中間操作)
  • Stream<T> sorted(); //line12
  • Stream<T> sorted(Comparator<? super T> comparator); //line13`
    產(chǎn)生一個自然順序排序或者指定排序條件的新流(中間操作)
  • void forEach(Consumer<? super T> action); //line17
  • void forEachOrdered(Consumer<? super T> action); //line18
    遍歷了流中的元素(終端操作)
  • Optional<T> min(Comparator<? super T> comparator) //line30
  • Optional<T> max(Comparator<? super T> comparator); //line31
    獲得流中最大最小值厢岂,比較器可以由自己定義光督,也可以使用JDK提供的(終端操作)

小結(jié)一下

這一篇主要是介紹了流API的一些關(guān)鍵方法,和一些關(guān)鍵的概念塔粒,雖然稍微枯燥了一點(diǎn)结借,但是,不能否認(rèn)卒茬,全面地學(xué)習(xí)流API映跟,會讓你對流API的認(rèn)識會更加的深刻,所以如果時(shí)間允許扬虚,請?jiān)僬J(rèn)真讀讀這一篇文章吧努隙,當(dāng)然,也可以在實(shí)踐中慢慢認(rèn)識它們辜昵,但是荸镊,對于這些基本概念的知識,你越早掌握堪置,對你的益處是更加大的躬存。到此為止,流API的基礎(chǔ)知識已經(jīng)學(xué)完了舀锨,后面的幾篇文章我們就要開始更加深入地理解和運(yùn)用他們實(shí)現(xiàn)一起強(qiáng)有力的功能了岭洲!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市坎匿,隨后出現(xiàn)的幾起案子盾剩,更是在濱河造成了極大的恐慌雷激,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件告私,死亡現(xiàn)場離奇詭異屎暇,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)驻粟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進(jìn)店門根悼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蜀撑,你說我怎么就攤上這事挤巡。” “怎么了酷麦?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵玄柏,是天一觀的道長。 經(jīng)常有香客問我贴铜,道長粪摘,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任绍坝,我火速辦了婚禮徘意,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘轩褐。我一直安慰自己椎咧,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布把介。 她就那樣靜靜地躺著勤讽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪拗踢。 梳的紋絲不亂的頭發(fā)上脚牍,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天,我揣著相機(jī)與錄音巢墅,去河邊找鬼诸狭。 笑死,一個胖子當(dāng)著我的面吹牛君纫,可吹牛的內(nèi)容都是我干的驯遇。 我是一名探鬼主播,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼蓄髓,長吁一口氣:“原來是場噩夢啊……” “哼叉庐!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起会喝,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤陡叠,失蹤者是張志新(化名)和其女友劉穎玩郊,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體匾竿,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瓦宜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年蔚万,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了岭妖。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡反璃,死狀恐怖昵慌,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情淮蜈,我是刑警寧澤斋攀,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站梧田,受9級特大地震影響淳蔼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜裁眯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一鹉梨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧穿稳,春花似錦存皂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至它改,卻和暖如春疤孕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背央拖。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工胰柑, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人爬泥。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓柬讨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親袍啡。 傳聞我的和親對象是個殘疾皇子踩官,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評論 2 359

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)境输,斷路器蔗牡,智...
    卡卡羅2017閱讀 134,696評論 18 139
  • Java流庫(java.util.stream) 流提供了一種讓我們可以在比集合更高的概念級別上指定計(jì)算的數(shù)據(jù)視圖...
    thorhill閱讀 4,843評論 0 4
  • 第一章 為什么要關(guān)心Java 8 使用Stream庫來選擇最佳低級執(zhí)行機(jī)制可以避免使用Synchronized(同...
    謝隨安閱讀 1,494評論 0 4
  • 參會人數(shù):14人颖系。應(yīng)到18人、實(shí)到14人 主持人:宏祥 紀(jì)律委員:張會斌 時(shí)間郎:春飛 記錄員:麗萍辩越,永萍 會議嘁扼,...
    蔣泳頻閱讀 122評論 0 2