[英]Consuming stream multiple times with Stream.sum()
stream 應該只運行一次(調用中間或終端 stream 操作)。
我明白了,但是為什么找到 stream 的總和不消耗它? 我可以運行下面的代碼,沒有任何例外。
double totalPrice = stream.mapToDouble(product -> product.price).sum();
List<Product> products = stream.map(this::convert).collect(Collectors.toList());
為什么sum
不是終端運算符? 與將 stream 元素收集到列表中有何不同?
未指定 stream 是否可以使用一次或多次。 文檔說“應該操作......只操作一次”,而不是“必須”或“可以”。
這取決於stream 的底層實現和來源。 因此,對於流來說,多次執行它的能力通常是未定義的。
您可能能夠找到可以使用兩次或多次的 stream,特別是對於自定義實現或預防檢測可能過於昂貴而無法實現的實現。
但同樣,文檔不支持它。 它可能是當前的實現,但這可以隨時更改,在任何 Java 版本中。 它可能會拋出異常,可能會導致錯誤行為,但未指定。
這是一個小示例,它使用sum()
引發異常,因為它具有這樣的檢測(JDK 11):
Stream<Integer> stream = List.of(1, 2, 3, 4).stream();
int first = stream
.mapToInt(i -> i)
.sum();
int second = stream
.mapToInt(i -> i)
.sum();
// throws IllegalStateException: stream has already been operated upon or closed
正如文檔所暗示的,其意圖絕對是不要多次使用 stream 。 因此,即使某個實現可能是可行的,也要避免它。
你可能會問自己為什么Stream
不支持多次迭代。 畢竟,像 ArrayList 這樣的ArrayList
沒有任何問題,而且這似乎是一個常見的用例。
流的scope比 collections 大得多。 在典型集合上創建的 stream 可能很容易支持多次迭代。 但是 stream 與文件或網絡連接等資源相關聯,例如Files.lines(...)
返回的 stream 不能。 這樣的功能對於文件來說將是非常耗費資源和昂貴的,甚至可能不支持其他功能,例如之后可能會關閉的 Web 連接。
更進一步,您可以輕松創建一個無限的 stream 生成隨機數:
Stream<Double> stream = Stream.generate(Math::random);
雖然它可以很容易地支持多種用途,但再次迭代時不可能再次生成相同的序列。
另一個例子,一個 stream 消耗資源而不恢復它們:
Queue<Integer> queue = ...
Stream<Integer> stream = Stream.generate(queue::poll);
這個 stream 將從隊列中刪除元素。 他們在 stream 使用后消失了。 stream 的另一個迭代將無法再接觸死物。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.