[英]Java 8 Stream - Filter and foreach method not printing as expected
我正在執行以下程序:
Stream.of("d2", "a2", "b1", "b3", "c")
.filter(s -> {
System.out.println("filter: " + s);
return true;
})
.forEach(s -> System.out.println("forEach: " + s));
我得到的輸出是:
filter: d2
forEach: d2
filter: a2
forEach: a2
filter: b1
forEach: b1
filter: b3
forEach: b3
filter: c
forEach: c
但是,我期待以下輸出:
filter: d2
filter: a2
filter: b1
filter: b3
filter: c
forEach: d2
forEach: a2
forEach: b1
forEach: b3
forEach: c
意思是,首先應該完全執行filter
方法循環,然后才能啟動forEach
方法循環。
有什么我做錯了嗎?
你的期望是錯誤的。
當執行終端操作forEach
,它一次消耗一個Stream
元素。 每消耗元件具有傳遞的所有的中間操作Stream
,這會導致filter
的元件上剛剛之前執行forEach
被同一元件上執行(假設元件經過filter
)。
換句話說,當Stream
管道中的下一個操作需要其下一個元素時(在您的情況下,下一個操作是forEach
), filter
被懶惰地應用於每個元素。
這意味着如果你的終端操作只需要處理一些Stream元素(例如,如果你用findFirst()
替換了forEach()
findFirst()
), filter()
操作只會在第一個元素傳遞之前執行(在您的示例中,這意味着僅針對第一個元素執行過濾器)。
Stream的處理將從終端操作開始,並逐個使用一個項目。 優點是:
程序必須只計算相關項目 - 例如,如果只需要一個項目,則只調用一次filter
:
Stream.of("d2", "a2", "b1", "b3", "c")
.filter(s -> {
System.out.println("filter: " + s);
return true;
})
.findAny()
.ifPresent(s -> System.out.println("forEach: " + s));
輸出:
filter: d2
forEach: d2
您甚至可以創建infinte Streams(否則將無法實現):
IntStream.iterate(0, i -> i+1)
.filter(s -> {
System.out.println("filter: " + s);
return true;
})
.peek(i -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
})
.forEach(s -> System.out.println("forEach: " + s));
輸出:
filter: 0
forEach: 0
filter: 1
forEach: 1
... (up to infinity)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.