如果你試圖對流操作中的流水線進行調試, 了解stream流水線每個操作之前和操作之后的中間值, 該如何去做?
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中的值,卻沒有任何輸出.
中間操作是流水線中的數據進行加工的, 它是一個懶操作, 並不會馬上執行, 需要等待有終止操作的時候才會執行.
終止操作是Stream的啟動操作, 當有終止操作的時候, Stream才會真正的開始執行.
因此, 這里可以解釋上面的peek操作是一個中間操作, 所以沒有任何輸出.
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
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中去.
覺得此文不錯, 點贊+轉發+關注, 本人非常感謝!