Java8特性②Stream簡介

流是什么

是Java API的新成員,它允許你以聲明性方式處理數據集合(通過查詢語句來表達,而不是臨時編寫一個實現)。可以把它們看成遍歷數據集的高級迭代器。此外流還可以透明地并行處理,無需寫任何多線程代碼了。如下面代碼所示:

public static List<String> getLowCalorisInJava8(List<Dish> dishes) {

    List<String> lowColorisDish = dishes.stream() //parallelStream() 并行流
                .filter((Dish d) -> d.getCalories() < 400) //篩選
                .sorted(Comparator.comparing(Dish::getCalories)) //排序
                .map(Dish::getName) //提取名稱
                .collect(Collectors.toList()); //將所有名稱存入List中

    return lowColorisDish;
}

Dish類

package com.company.bean;

import java.util.Arrays;
import java.util.List;

/**
 * Created by liuguoquan on 2017/4/26.
 */
public class Dish {

    private String name;
    private boolean vegetarian;
    private int calories;
    private Type type;

    public enum Type { MEAT, FISH, OTHER }

    public Dish(String name, boolean vegetarian, int calories, Type type) {
        this.name = name;
        this.vegetarian = vegetarian;
        this.calories = calories;
        this.type = type;
    }

    public String getName() {
        return name;
    }

    public boolean isVegetarian() {
        return vegetarian;
    }

    public int getCalories() {
        return calories;
    }

    public Type getType() {
        return type;
    }

    @Override
    public String toString() {
        return name;
    }

    public static final List<Dish> menu =
            Arrays.asList( new Dish("pork", false, 800, Dish.Type.MEAT),
                    new Dish("beef", false, 700, Dish.Type.MEAT),
                    new Dish("chicken", false, 400, Dish.Type.MEAT),
                    new Dish("french fries", true, 530, Dish.Type.OTHER),
                    new Dish("rice", true, 350, Dish.Type.OTHER),
                    new Dish("season fruit", true, 120, Dish.Type.OTHER),
                    new Dish("pizza", true, 550, Dish.Type.OTHER),
                    new Dish("prawns", false, 400, Dish.Type.FISH),
                    new Dish("salmon", false, 450, Dish.Type.FISH));
}

流簡介

流就是從支持數據處理操作的源生成的元素序列。

  • 元素序列:流也提供了一個接口,可以訪問特定元素類型的一組有序 值。因為集合是數據結構,所以它的主要目的是以特定的時間/空間復雜度存儲和訪問元 素(如 ArrayList 與 LinkedList )。但流的目的在于表達計算, 比如你前面見到的 filter、sorted和map。集合講的是數據,流講的是計算。

  • 源:流會使用一個提供數據的源,如集合、數組或輸入/輸出資源。 請注意,從有序集 合生成流時會保留原有的順序。由列表生成的流,其元素順序與列表一致。

  • 數據處理操作:流的數據處理功能支持類似于數據庫的操作,以及函數式編程語言中 的常用操作,如filter、map、reduce、find、match、sort等。流操作可以順序執 行,也可并行執行。

流操作的兩個重要的特點:

  • 流水線:很多流操作本身會返回一個流,這樣多個操作就可以鏈接起來,形成一個大的流水線。流水線的操作可以 看作對數據源進行數據庫式查詢。

  • 內部迭代:與使用迭代器顯式迭代的集合不同,流的迭代操作是在背后進行的。

流與集合

集合與流之間的差異就在于什么時候進行計算。集合是一個內存中的數據結構, 它包含數據結構中目前所有的值——集合中的每個元素都得先算出來才能添加到集合中。流則是在概念上固定的數據結構(你不能添加或刪除元素),其元素則是按需計算的。

流只能遍歷一次。遍歷完之后,這個流已經被消費掉了。可以從原始數據源那里再獲得一個新的流來重新遍歷一遍。

List<String> title = Arrays.asList("Java8", "In", "Action"); Stream<String> s = title.stream()
s.forEach(System.out::println); 
s.forEach(System.out::println); //java.lang.IllegalStateException:流已被操作

Collection接口需要用戶去做迭代(比如用for-each),這稱為外部迭代。Streams庫使用內部迭代——它幫你把迭代做了,還把得到的流值存在了某個地方,你只要給出一個函數說要干什么就可以了。Streams庫的內部迭代可以自動選擇一種適 合你硬件的數據表示和并行實現。與此相反,一旦通過寫for-each而選擇了外部迭代,那你基 本上就要自己管理所有的并行問題了。

流操作

java.util.stream.Stream 中的 Stream 接口定義了許多操作。它們可以分為兩大類。

  • 中間操作:filter、map、limit等可以連成一條流水線的操作;
  • 終端操作:collect等觸發流水線執行并關閉流的操作;

中間操作

諸如filter或sorted等中間操作會返回另一個流。這讓多個操作可以連接起來形成一個查 詢。重要的是,除非流水線上觸發一個終端操作,否則中間操作不會執行任何處理,這是因為中間操作一般都可以合并起來,在終端操作時一次性全部處理。盡管filter和map是兩個獨立的操作,但它們合并到同一次遍歷中了(我們把這種技術叫作循環 合并)。

終端操作

終端操作會從流的流水線生成結果。其結果是任何不是流的值,比如List、Integer,甚至void。

使用流

流的使用一般包括三件事:

  • 一個數據源(如集合)來執行一個查詢;
  • 一個中間操作鏈,形成一條流的流水線;
  • 一個終端操作,執行流水線,并能生成結果;

流的流水線背后的理念類似于構建器模式。在構建器模式中有一個調用鏈用來設置一套配 置(對流來說這就是一個中間操作鏈),接著是調用built方法(對流來說就是終端操作)。

參考資料

《Java 8 實戰》

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Java8 in action 沒有共享的可變數據,將方法和函數即代碼傳遞給其他方法的能力就是我們平常所說的函數式...
    鐵牛很鐵閱讀 1,259評論 1 2
  • 第一章 為什么要關心Java 8 使用Stream庫來選擇最佳低級執行機制可以避免使用Synchronized(同...
    謝隨安閱讀 1,508評論 0 4
  • 關于 本文是對 Brian Goetz的State of the Lambda: Libraries Editio...
    aaron688閱讀 1,360評論 0 5
  • 幾乎每個java應用程序都會制造和處理集合,要是沒有集合,還能做什么呢?盡管集合對于幾乎任何一個java應用都是不...
    GhostStories閱讀 427評論 0 3
  • 文/禾天 01 近日煩苦,常常失眠。夜深人靜時,燈盞昏昏,我閉著眼睛,困頓的想事情,卻苦于找不到釋放情緒的出口,睡...
    禾茶閱讀 281評論 2 12