The 'stream().forEach()' chain can be replaced with 'forEach()' (may change semantics)


對集合操作時,因不同的寫法Idea經常會提示:The 'stream().forEach()' chain can be replaced with 'forEach()' (may change semantics)
翻譯:'stream()。forEach()'鏈可以替換為'forEach()'(可能會改變語義)
解釋:對集合操作推薦直接使用Collection.forEach(),如果不需要流的話
流:流的好處不必多說
現象:

 

 擴展說明:

1.簡介

在java中有多種方式對集合進行遍歷。本教程中將看兩個類似的方法 Collection.stream().forEach()和Collection.forEach()。

在大多數情況下,兩者都會產生相同的結果,但是,我們會看到一些微妙的差異。

2.概述

首先,創建一個迭代列表:

最直接的方法是使用增強的for循環:

如果我們想使用函數式Java,我們也可以使用forEach()。我們可以直接在集合上這樣做:

或者,我們可以在集合的流上調用forEach():

兩個版本都將迭代列表並打印所有元素:

在這個簡單的例子中,我們使用的forEach()沒有區別

3.執行順序

Collection.forEach()使用集合的迭代器(如果指定了一個),集合里元素的處理順序是明確的。相反,Collection.stream().forEach()的處理順序是不明確的

在大多數情況下,我們選擇上述兩種方式的哪一種是沒有區別的。但是有時候有

3.1 Parallel Stream

並發流允許我們在多個線程中執行stream,在這種情況下,執行順序也不明確的。Java只需要在調用任何最終操作(例如Collectors.toList())之前完成所有線程。

看一個例子,首先直接在集合上調用forEach(),然后在並發流上調用:

如果我們多次運行代碼,我們會看到list.forEach()以插入順序處理元素,而 list.parallelStream().forEach()在每次運行會產生不同的結果

一個可能的輸出是:

ABCD CDBA

另一個是:

ABCD BDCA

3.2 自定義迭代器

讓我們使用自定義迭代器定義一個列表,以反向順序迭代集合:

當我們遍歷列表時,再次使用forEach()直接在集合上,然后在流上:

我們得到不同的結果:

DCBA  ABCD

結果不同的原因是在列表中使用的forEach()會使用自定義迭代器,而stream().forEach()只是從列表中逐個獲取元素,會忽略迭代器

4.修改集合

很多集合在遍歷的時候,不應該在結構上被修改(比如ArrayList或HashSet)。如果在迭代期間刪除或添加元素,會拋出ConcurrentModification異常。

此外,集合設計為快速失敗(fail-fast),這意味着一旦修改就拋出異常。

類似地,當我們在stream的執行期間添加或刪除元素時,我們將得到ConcurrentModification異常。但是,異常將在稍后拋出。

兩個forEach()方法之間的另一個細微差別是Java明確允許使用迭代器修改元素。相反,stream不能。

來看一下更詳細的例子。

4.1 刪除元素

定義一個列表,刪除最后一個元素(“D”):

遍歷列表時,在打印第一個元素(“A”)后刪除最后一個元素:

因為forEach()是快速失敗的,所以我們停止迭代並在處理下一個元素之前看到異常:

讓我們看看如果我們使用stream().forEach()會發生什么:

在這里,我們繼續迭代整個列表,然后才看到異常:

但是,Java並不保證會拋出ConcurrentModificationException。這意味着我們永遠不應該編寫依賴於此異常的程序。

4.2 改變元素

我們可以在迭代列表時更改元素:

但是,雖然使用Collection.forEach()或stream()。forEach()執行此操作沒有問題,但Java要求對流的操作是無干擾的。這意味着在執行流管道期間不應修改元素。

這背后的原因是流應該促進並行執行。在這里,修改流的元素可能會導致意外行為。

5.結論

在本文中,我們看到了一些示例,它們顯示了Collection.forEach()和Collection.stream().forEach()之間的細微差別。

但是,重要的是要注意上面顯示的所有示例僅僅是為了比較迭代集合的兩種方式。

如果我們不需要流但只想迭代集合,則第一個選擇應該直接在集合上使用forEach()。
這也是idea建議我們直接使用foeeach的原因 !

 

 
參考:https://baijiahao.baidu.com/s?id=1637952388544934539&wfr=spider&for=pc


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM