JDK 1.8 新特性學習(Stream)

Stream實現了對數據源的流式處理,它能夠並行操做,提升數據處理效率。

什麼是流

流不是集合,它不對數據作保存,只是最數據進行算法處理,好比最大值,最小值,排序等操做。Stream會在數據源內部隱式的遍歷進行處理。Stream會並行遍歷數據,將數據分紅若干段,同時進行處理,最終彙總結果一塊兒輸出。vue

Stream 就如同一個迭代器(Iterator),單向,不可往復,數據只能遍歷一次,遍歷過一次後即用盡了,就比如流水從面前流過,一去不復返。java

特色

首先對stream的操做能夠分爲兩類,中間操做(intermediate operations)和結束操做(terminal operations):node

  • 中間操做老是會惰式執行,調用中間操做只會生成一個標記了該操做的新stream。
  • 結束操做會觸發實際計算,計算髮生時會把全部中間操做積攢的操做以pipeline的方式執行,這樣能夠減小迭代次數。計算完成以後stream就會失效。
  • 無存儲。stream不是一種數據結構,它只是某種數據源的一個視圖,數據源能夠是一個數組,Java容器或I/O channel等。
  • 爲函數式編程而生。對stream的任何修改都不會修改背後的數據源,好比對stream執行過濾操做並不會刪除被過濾的元素,而是會產生一個不包含被過濾元素的新stream。
  • 惰式執行。stream上的操做並不會當即執行,只有等到用戶真正須要結果的時候纔會執行。
  • 可消費性。stream只能被「消費」一次,一旦遍歷過就會失效,就像容器的迭代器那樣,想要再次遍歷必須從新生成。

使用方法

1.構造流的方法

public class StreamStudy {
    
    public static void main(String[] args) throws Exception {
        //1. of
        Stream<String> stream  = Stream.of("hello","java","python");
        // 2. Arrays
        String [] strArray = new String[] {"hello","java","python"};
        stream = Stream.of(strArray);
        stream = Arrays.stream(strArray);
        // 3. Collections
        List<String> list = Arrays.asList(strArray);
        stream = list.stream();
        System.out.println(stream.findAny());
    }

}

最終只返回第一個結果: Optional[hello]python

2. 流轉換爲其它數據結構

public class StreamStudy {
    
    public static void main(String[] args) throws Exception {
        String [] strArray = new String[] {"hello","java","python"};
        List<String> list = Arrays.asList(strArray);
        // to array
        System.out.println(list.stream().toArray()[0]);
        // to list
        System.out.println(list.stream().collect(Collectors.toList()));
        // to string
        System.out.println(list.stream().collect(Collectors.joining()).toString());
    }

}

輸出:
hello
[hello, java, python]
hellojavapythonreact

3. 流的操做

  • Intermediate (map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered)
  • Terminal(forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator)
  • Short-circuiting(anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit)

一個流能夠後面跟隨零個或多個 intermediate 操做。其目的主要是打開流,作出某種程度的數據映射/過濾,而後返回一個新的流,交給下一個操做使用。這類操做都是惰性化的(lazy),就是說,僅僅調用到這類方法,並無真正開始流的遍歷。算法

一個流只能有一個 terminal 操做,當這個操做執行後,流就被使用「光」了,沒法再被操做。因此這一定是流的最後一個操做。Terminal 操做的執行,纔會真正開始流的遍歷,而且會生成一個結果,或者一個 side effect。編程

4.基礎的使用

1.map+forEach

public class StreamStudy {
    
    public static void main(String[] args) throws Exception {
        String [] strArray = new String[] {"hello","java","python"};
        List<String> list = Arrays.asList(strArray);
        list.stream().map((v) ->v.toUpperCase())
        .forEach(t -> System.out.println(t));
    }

}

將list中的全部字母轉換成大寫,而後遍歷輸出。 實際list中的值並無改變,咱們只是藉助Stream來作業務處理。
輸出 :
HELLO
JAVA
PYTHON數組

2.filter+map+forEach

public class StreamStudy {
    
    public static void main(String[] args) throws Exception {
        String [] strArray = new String[] {"hello","java","python"};
        List<String> list = Arrays.asList(strArray);
        list.stream().filter(f -> f.length()>4)
        .map(v ->v.toUpperCase())
        .forEach(t -> System.out.println(t));
    }

}

先filter過濾,而後map字母大寫,最後forEach輸出結果:
HELLO
PYTHON數據結構

3. filter+sorted+map+forEach

public class StreamStudy {
    
    public static void main(String[] args) throws Exception {
        String [] strArray = new String[] {"hello","java","python","node","react","vue"};
        List<String> list = Arrays.asList(strArray);
        list.stream().filter(f -> f.length()>3)
        .sorted((a,b) -> b.compareTo(a))
        .map(v ->v.toUpperCase())
        .forEach(t -> System.out.println(t));
    }

}

先filter過濾,而後sorted排序,而後map字母大寫,最後forEach輸出結果:
REACT
PYTHON
NODE
JAVA
HELLOide

4. filter+sorted+map+distinct+forEach

public class StreamStudy {
    
    public static void main(String[] args) throws Exception {
        String [] strArray = new String[] {"hello","java","python","node","react","vue","React"};
        List<String> list = Arrays.asList(strArray);
        list.stream().filter(f -> f.length()>3)
        .sorted((a,b) -> b.compareTo(a))
        .map(v ->v.toUpperCase())
        .distinct()
        .forEach(t -> System.out.println(t));
    }

}

distinct去重,使用 Object.equals(Object)來判斷是否重複,最終只留下一個REACT,結果:
REACT
PYTHON
NODE
JAVA
HELLO

5. filter+sorted+map+distinct+limit+forEach

public class StreamStudy {
    
    public static void main(String[] args) throws Exception {
        String [] strArray = new String[] {"hello","java","python","node","react","vue","React"};
        List<String> list = Arrays.asList(strArray);
        list.stream().filter(f -> f.length()>3)
        .sorted((a,b) -> b.compareTo(a))
        .map(v ->v.toUpperCase())
        .distinct()
        .limit(3)
        .forEach(t -> System.out.println(t));
    }

}

limit限制元素個數,這裏着要前3個結果:
REACT
PYTHON
NODE

6.filter+sorted+map+distinct+limit+peek+forEach

public class StreamStudy {
    
    public static void main(String[] args) throws Exception {
        String [] strArray = new String[] {"hello","java","python","node","react","vue","React"};
        List<String> list = Arrays.asList(strArray);
        list.stream().filter(f -> f.length()>3)
        .sorted((a,b) -> b.compareTo(a))
        .map(v ->v.toUpperCase())
        .distinct()
        .limit(3)
        .peek(p -> p.toLowerCase())
        .forEach(t -> System.out.println(t));
        
    }

}

peek會對每一個元素執行操做,並返回包含原stream元素的新Stream,什麼意思呢?先看結果:
REACT
PYTHON
NODE
並非咱們看到的小寫,由於peek產生的新的stream並非咱們已開始處理的Stream,因此咱們看到的仍是大寫。若是你的處理過程當中涉及一些額外邏輯,但不影響最終結果,那麼你可使用peek去搞一個新的Stream去處理。

7.總結

咱們主要使用的是Intermediate 中的方法進行數據處理,Terminal 中的方法只能使用一個,這意味着對流的處理終止,這時纔開始執行前面的那些Intermediate方法。最後對一些方法做一些解釋,就不一一演示了:
forEach遍歷、 forEachOrdered按順序遍歷、 toArray結果轉換成數組、 reduce結果中的元素進行組合、 collect結果轉換成集合、 min結果中最小值、 max結果中最大值、 count結果中元素數量、 anyMatch結果中存在元素知足某一條件、 allMatch結果中全部元素都知足某一條件、 noneMatch結果中全部元素都不知足某一條件、 findFirst結果中第一條數據 、 findAny結果中的任意一條數據、 iterator遍歷

歡迎關注個人公衆號mike啥都想搞,有更多教程資料相送。

相關文章
相關標籤/搜索