簡體   English   中英

了解java 8 stream的過濾方法

[英]Understanding java 8 stream's filter method

我最近在Java 8中了解了Stream s並看到了這個例子:

IntStream stream = IntStream.range(1, 20);

現在,讓我們說我們想要找到第一個可分為3和5的數字。我們可能會filter兩次並且findFirst如下:

OptionalInt result = stream.filter(x -> x % 3 == 0)
                               .filter(x -> x % 5 == 0)
                               .findFirst();

這聽起來很合理。 當我嘗試這樣做時出現了令人驚訝的部分:

OptionalInt result = stream.filter(x -> {System.out.println(x); return x % 3 == 0;})
                           .filter(x -> {System.out.println(x); return x % 5 == 0;})
                           .findFirst();

System.out.println(result.getAsInt());

我希望得到類似的東西: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20然后: 3 6 9 12 15 18 因為我們首先遍歷1到20之間的所有數字,只過濾那些可被3除數的數,然后迭代這個新的Stream並找到可被5除的那些。

但我得到了這個輸出: 1 2 3 3 4 5 6 6 7 8 9 9 10 11 12 12 13 14 15 15 15

看起來它並沒有超過所有數字。 此外,它看起來只檢查x % 5 == 0僅適用於可被3除數的數字。

我不明白為什么不迭代所有的數字。

這是代碼的在線片段: http//www.tryjava8.com/app/snippets/5454a7f2e4b070922a64002b

好吧,關於流的理解是,與列表不同,它們不一定(必然)保存所有項目,而是一次計算每個項目(懶惰評估)。

這意味着當你做IntStream stream = IntStream.range(1, 20); 你實際上並沒有創建一個包含20個項目的集合。 您創建了一個動態計算的集合。 每次調用此流的next將計算下一個項目。 其余的項目仍然“不存在”(有點說)。

過濾器也是如此。

當您將檢查除以3的過濾器添加時,您將獲得一個由2個計算組合而成的新流 - 第一個從1返回數字直到達到20,第二個計算返回除以3的數字。重要的是要了解每次只計算第一項。 這就是為什么當你添加除以5的檢查時它只能處理那些可以被3整除的項目。同樣可以解釋為什么打印停止在15. findFirst方法返回通過所有3個計算的第一個數字(1- 20范圍計算,3計算除以5除計算)。

Stream是一種有效處理集合的惰性評估機制。 這意味着除非最終(終端)操作需要,否則不評估Stream上的所有中間操作。

在您的示例中,終端操作是firstFirst() 這意味着Stream將評估中間操作的管道,直到找到通過將輸入Stream傳遞給所有中間操作而產生的單個int。

第二個過濾器只接收通過第一個過濾器的int,因此它只處理數字3,6,9,12,15然后停止,因為15通過過濾器,並為findFirst()操作提供它所需的唯一輸出。

只要終端操作仍然需要數據,第一個過濾器將僅處理輸入流的內部,因此它將僅處理1到15。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM