Java中的“流已被操作或關閉”異常

1.概述

在這篇簡短的文章中,我們將討論在Java 8中使用Stream類時可能遇到的常見Exception

IllegalStateException: stream has already been operated upon or closed.

我們將發現發生此異常的場景以及避免該異常的可能方法,並結合實際示例。

2.原因

在Java 8中,每個Stream類代表一個一次性使用的數據序列,並支持多個I / O操作。

Stream應操作一次(調用中間流或終端流操作)。如果Stream實現檢測到正在重用Stream則可能拋出IllegalStateException

每當在Stream對像上調用終端操作時,實例都會被消耗並關閉。

因此,只允許執行消耗**Stream ,**的單個操作**Stream** ,否則,我們將得到一個異常,指出該Stream已被操作或關閉。

讓我們看看如何將其轉換為實際示例:

Stream<String> stringStream = Stream.of("A", "B", "C", "D");

 Optional<String> result1 = stringStream.findAny();

 System.out.println(result1.get());

 Optional<String> result2 = stringStream.findFirst();

結果是:

A

 Exception in thread "main" java.lang.IllegalStateException:

 stream has already been operated upon or closed

調用#findAny()方法後, stringStream將關閉,因此,對Stream任何進一步操作都將引發IllegalStateException ,這就是在調用#findFirst()方法之後發生的情況。

3.解決方案

簡而言之,該解決方案包括每次需要時創建一個新的Stream

當然,我們可以手動執行此操作,但這是Supplier功能界面非常方便的地方:

Supplier<Stream<String>> streamSupplier

 = () -> Stream.of("A", "B", "C", "D");

 Optional<String> result1 = streamSupplier.get().findAny();

 System.out.println(result1.get());

 Optional<String> result2 = streamSupplier.get().findFirst();

 System.out.println(result2.get());

結果是:

A

 A

我們已經定義了類型為Stream<String>streamSupplier對象,它與#get()方法返回的類型完全相同。 Supplier基於不接收任何輸入並返回新Stream的lambda表達式。

Supplier上調用功能方法get()返回一個新創建的Stream對象,我們可以在該對像上安全地執行另一個Stream操作。

5.結論

在本快速教程中,我們了解瞭如何在Stream多次執行終端操作,同時避免了在Stream已關閉或對其進行操作時引發的著名的IllegalStateException

您可以在GitHub上找到本文的完整源代碼和所有代碼片段。