Stream中的Peek操作


1.引言

  如果你試圖對流操作中的流水線進行調試, 了解stream流水線每個操作之前和操作之后的中間值, 該如何去做?

  首先我們看一個例子, 使用forEach將流操作的結果打印出來.

 1 /**
 2  * @author lyh
 3  * @version v-1.0.0
 4  * @since 2021/5/28
 5  */
 6 public class PeekTestOne {
 7     public static void main(String[] args) {
 8         List<Integer> list = Arrays.asList(4, 7, 9, 11, 12);
 9         list.stream()
10                 .map(x -> x + 2)
11                 .filter(x -> x % 2 != 0)
12                 .limit(2)
13                 .forEach(System.out::println);
14     }
15 }
16 輸出結果如下:
17 9
18 11

  可以很明顯的看出, 一旦調用了forEach操作, 整個流就會恢復運行.並不能很好的幫助我們了解Stream流水線中的每個操作(如:map,filter,limit等)產生的輸出.

  再來看一個例子

 1 /**
 2  * @author lyh
 3  * @version v-1.0.0
 4  * @since 2021/5/28
 5  */
 6 public class PeekTestTwo {
 7     public static void main(String[] args) {
 8         Stream<Integer> stream = Arrays.asList(4, 7, 9, 11, 12).stream();
 9         stream.peek(System.out::println);
10 
11     }
12 }
13 這段代碼是想打印stream中的值,卻沒有任何輸出.

2.中間操作和終止操作

  中間操作是流水線中的數據進行加工的, 它是一個懶操作, 並不會馬上執行, 需要等待有終止操作的時候才會執行.

  終止操作是Stream的啟動操作, 當有終止操作的時候, Stream才會真正的開始執行.

  因此, 這里可以解釋上面的peek操作是一個中間操作, 所以沒有任何輸出.

3.使用peek進行debug操作

       peek的設計初衷就是在流的每個元素恢復運行之前的時候插入一個執行操作. 它不想forEach那樣恢復整個流的運行操作. 而是在一個元素上完成操作之后, 它只會將操作順承到流水線的下一個操作. 它能夠將中間變量的值輸出到日志. 有效的幫助我們了解流水線的每一步操作的輸出值.如下圖:

 1 /**
 2  * @author lyh
 3  * @version v-1.0.0
 4  * @since 2021/5/28
 5  */
 6 public class PeekTestThree {
 7     public static void main(String[] args) {
 8         List<Integer> list = Arrays.asList(4, 7, 9, 11, 12);
 9         list.stream()
10                 .peek(x -> System.out.println("stream: " + x))
11                 .map(x -> x + 2)
12                 .peek(x -> System.out.println("map: " + x))
13                 .filter(x -> x % 2 != 0)
14                 .peek(x -> System.out.println("filter: " + x))
15                 .limit(2)
16                 .peek(x -> System.out.println("limit: " + x))
17                 .collect(toList());
18     }
19 }
20 輸出結果如下:
21 stream: 4
22 map: 6
23 stream: 7
24 map: 9
25 filter: 9
26 limit: 9
27 stream: 9
28 map: 11
29 filter: 11
30 limit: 11
31 
32 Process finished with exit code 0

4.peek和map的區別

  使用peek操作流,流中的元素沒有改變。

 1 /**
 2  * @author lyh
 3  * @version v-1.0.0
 4  * @since 2021/5/28
 5  */
 6 public class PeekAndMapTestOne {
 7     public static void main(String[] args) {
 8         Arrays.asList("a","b")
 9                 .stream()
10                 .peek(x -> x.toUpperCase())
11                 .forEach(System.out::println);
12     }
13 }
14 輸出:
15 a
16 b
17 
18 Process finished with exit code 0

  使用map操作流,流中的元素有改變。

 1 /**
 2  * @author lyh
 3  * @version v-1.0.0
 4  * @since 2021/5/28
 5  */
 6 public class PeekAndMapTestTwo {
 7     public static void main(String[] args) {
 8         Arrays.asList("a","b")
 9                 .stream()
10                 .map(x -> x.toUpperCase())
11                 .forEach(System.out::println);
12     }
13 }
14 輸出:
15 A
16 B
17 
18 Process finished with exit code 0

  可以通過上面兩個例子看出,map操作是對元素進行了轉換。

  注意:peek對一個對象進行操作的時候,對象不變,但是可以改變對象里面的值.如下:

 1 /**
 2  * @author lyh
 3  * @version v-1.0.0
 4  * @since 2021/5/28
 5  */
 6 @Getter
 7 @Setter
 8 @AllArgsConstructor
 9 @ToString
10 public class Person {
11 
12     private String id;
13     private String name;
14 
15 }
16 ----------------------------------------------------------------------------
17 /**
18  * @author lyh
19  * @version v-1.0.0
20  * @since 2021/5/28
21  */
22 public class PeekAndMapTestThree {
23     public static void main(String[] args) {
24         Arrays.asList(new Person("001","zs"),new Person("002","ls"))
25                 .stream().peek(p -> p.setId("000")).forEach(System.out::println);
26     }
27 }
28 輸出:
29 Person(id=000, name=zs)
30 Person(id=000, name=ls)
31 
32 Process finished with exit code 0

  peek的定義

1 Stream<T> peek(Consumer<? super T> action);

  peek方法接收一個Consumer的入參. 了解λ表達式的應該明白 Consumer的實現類應該只有一個方法,該方法返回類型為void. 它只是對Stream中的元素進行某些操作,但是操作之后的數據並不返回到Stream中,所以Stream中的元素還是原來的元素.

  map的定義

1 <R> Stream<R> map(Function<? super T, ? extends R> mapper);

  map方法接收一個Function作為入參. Function是有返回值的, 這就表示map對Stream中的元素的操作結果都會返回到Stream中去.

 ​   覺得此文不錯, 點贊+轉發+關注, 本人非常感謝!


免責聲明!

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



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