重走Java基礎之Streams(一)

作者:知秋
來源:重走Java基礎之Streams(一)


因為經常逛stackoverflow,最近也在看reactive和storm以及前一陣子也用流式ORM框架speedmentSpringboot整合改造了migo2.0中的單點登錄,深深的感受到java8已經融入我們很深了,尤其是Spring5對其進行大力支持,覺得有必要再對自己的知識整理一下,順帶就把stackoverflow一些東西自己拿過來整理翻譯一下,里面也會加入一些自己的理解

Introduction

流表示一系列元素并支持不同類型的操作來對這些元素執行計算。在Java 8中,Collection接口有兩種方法來生成Stream

  • 1)stream()和
  • 2) parallelStream()

流操作包括中間或終端。 中間操作返回一個流,所以我們可以鏈接多個中間操作而不使用分號。 終端操作是void的或返回非流結果。

Examples

Using Streams

A Stream是可以執行順序和并行聚合操作的一系列元素 。 任何給定的“Stream”都可能有無限量的數據流過它。 你所得到的結果是從“Stream”接收的數據在到達時被單獨處理,而不是完全對數據執行批處理。 當與lambda表達式 結合時,它們提供了使用函數方法對數據序列執行操作的簡明方法。

Example: (see it work on Ideone)

Stream<String> fruitStream = Stream.of("apple", "banana", "pear", "kiwi", "orange");

fruitStream.filter(s -> s.contains("a"))
           .map(String::toUpperCase)
           .sorted()
           .forEach(System.out::println);

Output:

APPLE
BANANA
ORANGE
PEAR

上述代碼執行的操作可以總結如下:

  1. 使用靜態工廠方法Stream.of(values)創建一個包含fruit String的順序排序StreamStream 元素

  2. filter()操作僅保留與給定謂詞(由謂詞返回true測試時的元素)匹配的元素。 在這種情況下,它保留含有“a”的元素。 謂詞作為lambda表達式給出。

  3. map() 操作轉換 每個元素使用給定的函數,稱為映射器。 在這種情況下,每個fruit String使用method-reference映射到將string字符串轉換為大寫版本String::toUppercase

    Note 如果映射函數返回與其輸入參數不同的類型,那么map()操作將返回具有不同泛型類型的流。 例如在一個Stream調用.map(String :: isEmpty)返回一個Stream<Boolean>

  4. sorted()操作對Stream的元素進行排序 根據它們的自然排序(根據在'String'的情況下對所在字典的順序,其實都知道)。

  5. 最后, forEach(action) 操作執行一個動作,作用于“Stream”的每個元素,將其傳遞給一個 Consumer。 在該示例中,每個元素只是被打印到控制臺。 該操作是終端操作,因此不可能再次進行操作。

  6. NoteStream中定義的操作之所以被執行,是因為最后有終端操作。 假如沒有終端操作,'Stream'將不被處理,因為'Stream'輸出不被任何終端操作使用(省的浪費計算資源,所以很多書上稱之為被動式foreach)。

Chained operations

操作(如上所示)鏈接在一起以形成可以被視為對數據的查詢


Reusing Streams

一個Stream不能重復使用。 一旦調用任何中間或終端操作,“Stream”對象將變得不可用。 Stream代替地使用中間Stream對象以便將中間操作鏈接在一起通過一系列Stream操作來生成一個Stream對象作為中間對象,最后再調用這個生成的Stream對象來完成最終的操作,最后一步的操作只能進行一次,之后,此流已經沒了(生命周期已結束)。

Example:

Stream<String> stream =
    Stream.of("d2", "a2", "b1", "b3", "c")
        .filter(s -> s.startsWith("a"));

stream.anyMatch(s -> true);  // The Stream has been used and is now consumed.
stream.noneMatch(s -> true); // IllegalStateException; stream was already used

Closing Streams

Stream接口擴展了 AutoCloseable。Streams可以通過調用 close方法或使用try-with -resource語句來關閉。

請注意,Stream通常不必關閉。僅需要關閉在IO通道上運行的流。 大多數Stream 型不對資源操作,因此不需要關閉。

Stream 應該關閉的示例用例是,當您從文件創建一個Stream 行時:

try(final Stream<String> lines = Files.lines(Paths.get("somePath"))){
    lines.forEach(System.out::println);
}

Stream接口也聲明了Stream.onClose() 方法,它允許你注冊 Runnable處理程序,當 流關閉。 一個示例用例是產生流的代碼需要知道它何時被消耗以執行一些清理。

public Stream<String>streamAndDelete(Path path) throws IOException {
    return Files.lines(path)
        .onClose(()->someClass.deletePath(path));
}

運行處理程序只有在調用close() 方法時才會執行,例如通過try-with-resources:

Path myPath = Paths.get("somePath");

try(final Stream<String> lines = streamAndDelete(myPath)){
    lines.forEach(System.out::println);
}
Files.exists(myPath); // returns false

If close() isn't called, explicitly or implicitly, then the handler will not be called either:
如果沒有明確或隱式地調用close(),那么處理程序不會被調用:

streamAndDelete(myPath)
    .forEach(System.out::println);
Files.exists(myPath); // returns true 

Processing Order

Stream對象的處理可以是順序或 parallel(并行)

在** sequential **模式中,按照“Stream”的源的順序處理元素。 如果Stream是有序的(例如 SortedMap實現或List,處理過程保證匹配源的排序。 然而,在其他情況下,應注意不要依賴于順序(參見:是Java的HashMap`` keySet()迭代順序一致?)。

Example:

List<Integer> integerList = Arrays.asList(0, 1, 2, 3, 42); 

// sequential 
long howManyOddNumbers = integerList.stream()
                                    .filter(e -> (e % 2) == 1).count(); 

System.out.println(howManyOddNumbers); // Output: 2

Live on Ideone

并行模式允許在多個核上使用多個線程,但不能保證處理元素的順序。

如果在順序的 Stream 上雖然調用了多個方法,則不一定必須要調用每個方法。 例如,如果一個 Stream 被過濾,并且元素的數量減少到一,則不會發生對諸如sort的方法的后續調用。 這可以提高順序的Stream的性能 - 這是一個并行的Stream不可能實現的優化。

Example:

// parallel
long howManyOddNumbersParallel = integerList.parallelStream()
                                            .filter(e -> (e % 2) == 1).count();
System.out.println(howManyOddNumbersParallel); // Output: 2

Live on Ideone


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

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,948評論 18 139
  • 來源:重走Java基礎之Streams(四)作者:知秋博客:一葉知秋轉載請注明來源和作者! 接上篇重走Java基礎...
    極樂君閱讀 482評論 0 3
  • 來源:重走Java基礎之Streams(二)作者:知秋(極樂科技知乎專欄原創作者)博客:一葉知秋 接上篇重走Jav...
    極樂君閱讀 530評論 0 2
  • 本文采用實例驅動的方式,對JAVA8的stream API進行一個深入的介紹。雖然JAVA8中的stream AP...
    浮梁翁閱讀 25,873評論 3 50
  • 第一章 為什么要關心Java 8 使用Stream庫來選擇最佳低級執行機制可以避免使用Synchronized(同...
    謝隨安閱讀 1,518評論 0 4