當(dāng)前位置:首頁 > 公眾號(hào)精選 > 架構(gòu)師社區(qū)
[導(dǎo)讀]寫在前面 先說點(diǎn)題外話:不少讀者工作幾年后,仍然在使用Java7之前版本的方法,對(duì)于Java8版本的新特性,甚至是Java7的新特性幾乎沒有接觸過。真心想對(duì)這些讀者說:你真的需要了解下Java8甚至以后版本的新特性了。 今天,一名讀者出去面試,面試官問他:說說Ja

【Java8新特性】面試官問我:Java8中創(chuàng)建Stream流有哪幾種方式?

寫在前面

先說點(diǎn)題外話:不少讀者工作幾年后,仍然在使用Java7之前版本的方法,對(duì)于Java8版本的新特性,甚至是Java7的新特性幾乎沒有接觸過。真心想對(duì)這些讀者說:你真的需要了解下Java8甚至以后版本的新特性了。


今天,一名讀者出去面試,面試官問他:說說Java8中創(chuàng)建Stream流有哪幾種方式?他竟然沒回答上來?。?/p>

Stream概述

Java8中有兩大最為重要的改變。第一個(gè)是 Lambda 表達(dá)式;另外一個(gè)則是 Stream API(java.util.stream.*)。

Stream 是 Java8 中處理集合的關(guān)鍵抽象概念,它可以指定你希望對(duì)集合進(jìn)行的操作,可以執(zhí)行非常復(fù)雜的查找、過濾和映射數(shù)據(jù)等操作。使用Stream API 對(duì)集合數(shù)據(jù)進(jìn)行操作,就類似于使用 SQL 執(zhí)行的數(shù)據(jù)庫查詢。也可以使用 Stream API 來并行執(zhí)行操作。簡(jiǎn)而言之,Stream API 提供了一種高效且易于使用的處理數(shù)據(jù)的方式。

何為Stream?

流(Stream) 到底是什么呢?

可以這么理解流:流就是數(shù)據(jù)渠道,用于操作數(shù)據(jù)源(集合、數(shù)組等)所生成的元素序列。

“集合講的是數(shù)據(jù),流講的是計(jì)算!”

注意:

①Stream 自己不會(huì)存儲(chǔ)元素。

②Stream 不會(huì)改變?cè)磳?duì)象。相反,他們會(huì)返回一個(gè)持有結(jié)果的新Stream。

③Stream 操作是延遲執(zhí)行的。這意味著他們會(huì)等到需要結(jié)果的時(shí)候才執(zhí)行。

Stream操作步驟

1.創(chuàng)建 Stream

一個(gè)數(shù)據(jù)源(如:集合、數(shù)組), 獲取一個(gè)流。

2.中間操作

一個(gè)中間操作鏈,對(duì)數(shù)據(jù)源的數(shù)據(jù)進(jìn)行處理。

3.終止操作(終端操作)

一個(gè)終止操作,執(zhí)行中間操作鏈,并產(chǎn)生結(jié)果 。

【Java8新特性】面試官問我:Java8中創(chuàng)建Stream流有哪幾種方式?

如何創(chuàng)建Stream流?

這里,創(chuàng)建測(cè)試類TestStreamAPI1,所有的操作都是在TestStreamAPI1類中完成的。

(1)通過Collection系列集合提供的stream()方法或者parallelStream()方法來創(chuàng)建Stream。

在Java8中,Collection 接口被擴(kuò)展,提供了兩個(gè)獲取流的默認(rèn)方法,如下所示。

default Stream<E> stream() {
    return StreamSupport.stream(spliterator(), false);
}
default Stream<E> parallelStream() {
    return StreamSupport.stream(spliterator(), true);
}

其中,stream()方法返回一個(gè)順序流,parallelStream()方法返回一個(gè)并行流。

我們可以使用如下代碼方式來創(chuàng)建順序流和并行流。

List<String> list = new ArrayList<>();
list.stream();
list.parallelStream();

(2)通過Arrays中的靜態(tài)方法stream()獲取數(shù)組流。

Java8 中的 Arrays類的靜態(tài)方法 stream() 可以獲取數(shù)組流 ,如下所示。

public static <T> Stream<T> stream(T[] array) {
    return stream(array, 0, array.length);
}

上述代碼的的作用為:傳入一個(gè)泛型數(shù)組,返回這個(gè)泛型的Stream流。

除此之外,在Arrays類中還提供了stream()方法的如下重載形式。

public static <T> Stream<T> stream(T[] array) {
    return stream(array, 0, array.length);
}

public static <T> Stream<T> stream(T[] array, int startInclusive, int endExclusive) {
    return StreamSupport.stream(spliterator(array, startInclusive, endExclusive), false);
}

public static IntStream stream(int[] array) {
    return stream(array, 0, array.length);
}

public static IntStream stream(int[] array, int startInclusive, int endExclusive) {
    return StreamSupport.intStream(spliterator(array, startInclusive, endExclusive), false);
}

public static LongStream stream(long[] array) {
    return stream(array, 0, array.length);
}

public static LongStream stream(long[] array, int startInclusive, int endExclusive) {
    return StreamSupport.longStream(spliterator(array, startInclusive, endExclusive), false);
}

public static DoubleStream stream(double[] array) {
    return stream(array, 0, array.length);
}

public static DoubleStream stream(double[] array, int startInclusive, int endExclusive) {
    return StreamSupport.doubleStream(spliterator(array, startInclusive, endExclusive), false);
}

基本上能夠滿足基本將基本類型的數(shù)組轉(zhuǎn)化為Stream流的操作。

我們可以通過下面的代碼示例來使用Arrays類的stream()方法來創(chuàng)建Stream流。

Integer[] nums = new Integer[]{1,2,3,4,5,6,7,8,9};
Stream<Integer> numStream = Arrays.stream(nums);

(3)通過Stream類的靜態(tài)方法of()獲取數(shù)組流。

可以使用靜態(tài)方法 Stream.of(), 通過顯示值創(chuàng)建一個(gè)流。它可以接收任意數(shù)量的參數(shù)。

我們先來看看Stream的of()方法,如下所示。

public static<T> Stream<T> of(T t) {
    return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
}
@SafeVarargs
@SuppressWarnings("varargs"
public static<T> Stream<T> of(T... values) {
    return Arrays.stream(values);
}

可以看到,在Stream類中,提供了兩個(gè)of()方法,一個(gè)只需要傳入一個(gè)泛型參數(shù),一個(gè)需要傳入一個(gè)可變泛型參數(shù)。

我們可以使用下面的代碼示例來使用of方法創(chuàng)建一個(gè)Stream流。

Stream<String> strStream = Stream.of("a""b""c");

(4)創(chuàng)建無限流

可以使用靜態(tài)方法 Stream.iterate() 和Stream.generate(), 創(chuàng)建無限流。

先來看看Stream類中iterate()方法和generate()方法的源碼,如下所示。

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);
}

通過源碼可以看出,iterate()方法主要是使用“迭代”的方式生成無限流,而generate()方法主要是使用“生成”的方式生成無限流。我們可以使用下面的代碼示例來使用這兩個(gè)方法生成Stream流。

  • 迭代

Stream<Integer> intStream = Stream.iterate(0, (x) -> x + 2);
intStream.forEach(System.out::println);

運(yùn)行上述代碼,會(huì)在終端一直輸出偶數(shù),這種操作會(huì)一直持續(xù)下去。如果我們只需要輸出10個(gè)偶數(shù),該如何操作呢?其實(shí)也很簡(jiǎn)單,使用Stream對(duì)象的limit方法進(jìn)行限制就可以了,如下所示。

Stream<Integer> intStream = Stream.iterate(0, (x) -> x + 2);
intStream.limit(10).forEach(System.out::println);


  • 生成

Stream.generate(() -> Math.random()).forEach(System.out::println);

上述代碼同樣會(huì)一直輸出隨機(jī)數(shù),如果我們只需要輸出5個(gè)隨機(jī)數(shù),則只需要使用limit()方法進(jìn)行限制即可。

Stream.generate(() -> Math.random()).limit(5).forEach(System.out::println);

(5)創(chuàng)建空流

在Stream類中提供了一個(gè)empty()方法,如下所示。

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

我們可以使用Stream類的empty()方法來創(chuàng)建一個(gè)空Stream流,如下所示。

Stream<String> empty = Stream.empty();


特別推薦一個(gè)分享架構(gòu)+算法的優(yōu)質(zhì)內(nèi)容,還沒關(guān)注的小伙伴,可以長(zhǎng)按關(guān)注一下:

【Java8新特性】面試官問我:Java8中創(chuàng)建Stream流有哪幾種方式?

長(zhǎng)按訂閱更多精彩▼

【Java8新特性】面試官問我:Java8中創(chuàng)建Stream流有哪幾種方式?

如有收獲,點(diǎn)個(gè)在看,誠(chéng)摯感謝

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉
關(guān)閉