先說點題外話:很多讀者工做幾年後,仍然在使用Java7以前版本的方法,對於Java8版本的新特性,甚至是Java7的新特性幾乎沒有接觸過。真心想對這些讀者說:你真的須要瞭解下Java8甚至之後版本的新特性了。java
今天,一名讀者出去面試,面試官問他:說說Java8中建立Stream流有哪幾種方式?他居然沒回答上來!!面試
Java8中有兩大最爲重要的改變。第一個是 Lambda 表達式;另一個則是 Stream API(java.util.stream.*)。數據庫
Stream 是 Java8 中處理集合的關鍵抽象概念,它能夠指定你但願對集合進行的操做,能夠執行很是複雜的查找、過濾和映射數據等操做。使用Stream API 對集合數據進行操做,就相似於使用 SQL 執行的數據庫查詢。也可使用 Stream API 來並行執行操做。簡而言之,Stream API 提供了一種高效且易於使用的處理數據的方式。數組
流(Stream) 究竟是什麼呢?微信
能夠這麼理解流:流就是數據渠道,用於操做數據源(集合、數組等)所生成的元素序列。app
「集合講的是數據,流講的是計算! 」dom
注意:ide
①Stream 本身不會存儲元素。學習
②Stream 不會改變源對象。相反,他們會返回一個持有結果的新Stream。測試
③Stream 操做是延遲執行的。這意味着他們會等到須要結果的時候才執行。
1.建立 Stream
一個數據源(如: 集合、數組), 獲取一個流。
2.中間操做
一箇中間操做鏈,對數據源的數據進行處理。
3.終止操做(終端操做)
一個終止操做,執行中間操做鏈,併產生結果 。
這裏,建立測試類TestStreamAPI1,全部的操做都是在TestStreamAPI1類中完成的。
(1)經過Collection系列集合提供的stream()方法或者parallelStream()方法來建立Stream。
在Java8中,Collection 接口被擴展,提供了兩個獲取流的默認方法,以下所示。
default Stream<E> stream() { return StreamSupport.stream(spliterator(), false); } default Stream<E> parallelStream() { return StreamSupport.stream(spliterator(), true); }
其中,stream()方法返回一個順序流,parallelStream()方法返回一個並行流。
咱們可使用以下代碼方式來建立順序流和並行流。
List<String> list = new ArrayList<>(); list.stream(); list.parallelStream();
(2)經過Arrays中的靜態方法stream()獲取數組流。
Java8 中的 Arrays類的靜態方法 stream() 能夠獲取數組流 ,以下所示。
public static <T> Stream<T> stream(T[] array) { return stream(array, 0, array.length); }
上述代碼的的做用爲:傳入一個泛型數組,返回這個泛型的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); }
基本上可以知足基本將基本類型的數組轉化爲Stream流的操做。
咱們能夠經過下面的代碼示例來使用Arrays類的stream()方法來建立Stream流。
Integer[] nums = new Integer[]{1,2,3,4,5,6,7,8,9}; Stream<Integer> numStream = Arrays.stream(nums);
(3)經過Stream類的靜態方法of()獲取數組流。
可使用靜態方法 Stream.of(), 經過顯示值建立一個流。它能夠接收任意數量的參數。
咱們先來看看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類中,提供了兩個of()方法,一個只須要傳入一個泛型參數,一個須要傳入一個可變泛型參數。
咱們可使用下面的代碼示例來使用of方法建立一個Stream流。
Stream<String> strStream = Stream.of("a", "b", "c");
(4)建立無限流
可使用靜態方法 Stream.iterate() 和Stream.generate(), 建立無限流。
先來看看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()方法主要是使用「生成」的方式生成無限流。咱們可使用下面的代碼示例來使用這兩個方法生成Stream流。
Stream<Integer> intStream = Stream.iterate(0, (x) -> x + 2); intStream.forEach(System.out::println);
運行上述代碼,會在終端一直輸出偶數,這種操做會一直持續下去。若是咱們只須要輸出10個偶數,該如何操做呢?其實也很簡單,使用Stream對象的limit方法進行限制就能夠了,以下所示。
Stream<Integer> intStream = Stream.iterate(0, (x) -> x + 2); intStream.limit(10).forEach(System.out::println);
Stream.generate(() -> Math.random()).forEach(System.out::println);
上述代碼一樣會一直輸出隨機數,若是咱們只須要輸出5個隨機數,則只須要使用limit()方法進行限制便可。
Stream.generate(() -> Math.random()).limit(5).forEach(System.out::println);
(5)建立空流
在Stream類中提供了一個empty()方法,以下所示。
public static<T> Stream<T> empty() { return StreamSupport.stream(Spliterators.<T>emptySpliterator(), false); }
咱們可使用Stream類的empty()方法來建立一個空Stream流,以下所示。
Stream<String> empty = Stream.empty();
若是以爲文章對你有點幫助,請微信搜索並關注「 冰河技術 」微信公衆號,跟冰河學習Java8新特性。
最後,附上Java8新特性核心知識圖,祝你們在學習Java8新特性時少走彎路。