跟我学 Java 8 新特性之 Stream 流(二)关键知识点
轉(zhuǎn)載自? ?跟我學(xué) Java 8 新特性之 Stream 流(二)關(guān)鍵知識點
我們的第一篇文章,主要是通過一個Demo,讓大家體驗了一下使用流API的那種酣暢淋漓的感覺。如果你沒有實踐,我還是再次呼吁你動手敲一敲,自己實實在跑一遍上一篇的Demo。
相信你的感受和理解也會隨之加深的。繼續(xù)探索流API的高級功能之前,我們先從接口級別全面了解一下流API,這個對于我們來說是至關(guān)重要的。接下來,我給大家準(zhǔn)備了一張流API關(guān)鍵知識點的UML圖。但是大家只需要花一兩分鐘,整理看一下就可以了,不需要記住,先有個印象,后面我給大家講解一些關(guān)鍵的方法:
流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ù)組,基本上都不會出現(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接口是最具代表性的,所以我們就選擇它來講解,其實在我們學(xué)完Stream接口,其它的三個接口,在使用上基本是一致的了,我們上一篇的Demo基本上也是使用Stream接口來做的練習(xí)。
我們回想一下:在上一個Demo中我們通過集合框架的stream()方法,就能返回一個流了,它的返回類型就是Stream,比如我們Stream,由此得知,Stream接口里的類型參數(shù)T就是流中的元素的類型。木有錯,就是這樣滴。到這里,整個系列你們已經(jīng)全部學(xué)會了,下課。
?
戰(zhàn)斗才剛剛開始!
?
現(xiàn)在是時候開始記憶一些知識了.
BaseStream詳解:
public interface BaseStream<T, S extends BaseStream<T, S>> extends AutoCloseable {Iterator<T> iterator();//line2Spliterator<T> spliterator();//line3boolean isParallel();//line4S sequential();//line5S parallel();//line6S unordered();//line7S onClose(Runnable closeHandler);//line8@Overridevoid close();//line10}-
Iterator?iterator();?//line2?獲得流的迭代器,并返回對該迭代器的引用(終端操作)
-
Spliterator?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)閉該流時,將調(diào)用這個處理程序。(中間操作)
-
void close();?//line10?從AutoCloseable繼承來的,調(diào)用注冊關(guān)閉處理程序,關(guān)閉調(diào)用流(很少會被使用到)
"終端操作"&"中間操作"
細(xì)心的同學(xué)應(yīng)該注意到了,BaseStream接口里面的很多方法都在最后標(biāo)識了(終端操作)和(中間操作),它們之間的區(qū)別是非常重要的。
-
終端操作 會消費流,這種操作會產(chǎn)生一個結(jié)果的,比如上面的 iterator()和 spliterator(),以及上一篇中提到的min()和max(),或者是執(zhí)行某一種操作,比如上一篇的forEach(),如果一個流被消費過了,那它就不能被重用的。
-
中間操作 中間操作會產(chǎn)生另一個流。因此中間操作可以用來創(chuàng)建執(zhí)行一系列動作的管道。一個特別需要注意的點是:中間操作不是立即發(fā)生的。相反,當(dāng)在中間操作創(chuàng)建的新流上執(zhí)行完終端操作后,中間操作指定的操作才會發(fā)生。所以中間操作是延遲發(fā)生的,中間操作的延遲行為主要是讓流API能夠更加高效地執(zhí)行。
"中間操作"的狀態(tài)
流的中間操作,可以為分 無狀態(tài)操作和 有狀態(tài)操作兩種,在無狀態(tài)操作中,在處理流中的元素時,會對當(dāng)前的元素進(jìn)行單獨處理。比如:謂詞過濾操作,因為每個元素都是被單獨進(jìn)行處理的,所有它和流中的其它元素?zé)o關(guān),因此被稱為無狀態(tài)操作;而在有狀態(tài)操作中,某個元素的處理可能依賴于其他元素。比如查找最小值,最大值,和排序,因為他們都依賴于其他的元素。因此為稱為有狀態(tài)操作。?
當(dāng)需要進(jìn)行并行處理流時,有狀態(tài)的操作和無狀態(tài)的區(qū)別是非常重要的,因為有狀態(tài)操作可能需要幾次處理才能完成,后面的文章我將會給大家詳細(xì)地講,現(xiàn)在只需要正常學(xué)習(xí)下去就可以了
另外,指出一點,如果大家了解泛型的話,應(yīng)該知道,泛型的類型參數(shù)只能是引用類型,因此Stream操作的對象只能是引用類型的,不能用于基本類型。當(dāng)然官方早已考慮到這一點了,前面你們看到的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);//line3IntStream mapToInt(ToIntFunction<? super T> mapper);//line4LongStream 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();//line12Stream<T> sorted(Comparator<? super T> comparator);//line13Stream<T> peek(Consumer<? super T> action);Stream<T> limit(long maxSize);Stream<T> skip(long n);void forEach(Consumer<? super T> action);//line17void forEachOrdered(Consumer<? super T> action);//line18Object[] 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);//line30Optional<T> max(Comparator<? super T> comparator);//line31long 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 factoriespublic 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 safepublic 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;@Overridepublic boolean hasNext() {return true;}@Overridepublic 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?filter(Predicate?predicate);?//line2?產(chǎn)生一個新流,其中包含調(diào)用流中滿足predicate指定的謂詞元素(中間操作)
-
Stream?map(Function?mapper);?//line3?產(chǎn)生一個新流,對調(diào)用流中的元素應(yīng)用mapper,新流中包含這些元素。(中間操作)
-
IntStream mapToInt(ToIntFunction?mapper);?//line4?對調(diào)用流中元素應(yīng)用mapper,產(chǎn)生包含這些元素的一個新IntStream流。(中間操作)
-
Stream?sorted();?//line12
-
Stream?sorted(Comparator?comparator);?//line13` 產(chǎn)生一個自然順序排序或者指定排序條件的新流(中間操作)
-
void forEach(Consumer?action);?//line17
-
void forEachOrdered(Consumer?action);?//line18?遍歷了流中的元素(終端操作)
-
Optional?min(Comparator?comparator)?//line30
-
Optional?max(Comparator?comparator);?//line31?獲得流中最大最小值,比較器可以由自己定義,也可以使用JDK提供的(終端操作)
小結(jié)一下
這一篇主要是介紹了流API的一些關(guān)鍵方法,和一些關(guān)鍵的概念,雖然稍微枯燥了一點,但是,不能否認(rèn),全面地學(xué)習(xí)流API,會讓你對流API的認(rèn)識會更加的深刻,所以如果時間允許,請再認(rèn)真讀讀這一篇文章吧,當(dāng)然,也可以在實踐中慢慢認(rèn)識它們,但是,對于這些基本概念的知識,你越早掌握,對你的益處是更加大的。
總結(jié)
以上是生活随笔為你收集整理的跟我学 Java 8 新特性之 Stream 流(二)关键知识点的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 9个最佳美容院标志"如何免费获得[202
- 下一篇: 自己怎么建立公司网站(自己怎么建立公司网