簡體   English   中英

Java 8 Stream - 過濾和foreach方法不按預期打印

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

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