[英]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.