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上找到本文的完整源代碼和所有代碼片段。