關於stream.foreach()和stream.peek()的區別解析

改思考來源於日常工作中,特記此心得。

 

思考:如何快速將list中的每個item內部屬性值改變並進行其他流體操作呢?

下面做個測試:如何在list中根據某個屬性的最小值取出該對象

 

1:隨便新建一個測試bean:

 

 1 package com.dev.model;
 2 
 3 import javax.persistence.*;
 4 
 5 public class Aopi {
 6     /**
 7      * id
 8      */
 9     @Id
10     @GeneratedValue(strategy = GenerationType.IDENTITY)
11     private Integer id;
12 
13     /**
14      * 姓名
15      */
16     private String name;
17 
18     /**
19      * 年齡
20      */
21     private Integer age;
22 
23     /**
24      * 獲取id
25      *
26      * @return id - id
27      */
28     public Integer getId() {
29         return id;
30     }
31 
32     /**
33      * 設置id
34      *
35      * @param id id
36      */
37     public void setId(Integer id) {
38         this.id = id;
39     }
40 
41     /**
42      * 獲取姓名
43      *
44      * @return name - 姓名
45      */
46     public String getName() {
47         return name;
48     }
49 
50     /**
51      * 設置姓名
52      *
53      * @param name 姓名
54      */
55     public void setName(String name) {
56         this.name = name;
57     }
58 
59     /**
60      * 獲取年齡
61      *
62      * @return age - 年齡
63      */
64     public Integer getAge() {
65         return age;
66     }
67 
68     /**
69      * 設置年齡
70      *
71      * @param age 年齡
72      */
73     public void setAge(Integer age) {
74         this.age = age;
75     }
76 
77     public Aopi(String name, Integer age) {
78         this.name = name;
79         this.age = age;
80     }
81 
82     public Aopi() {
83     }
84 
85     @Override
86     public String toString() {
87         return "Aopi{" +
88                 "id=" + id +
89                 ", name='" + name + '\'' +
90                 ", age=" + age +
91                 '}';
92     }
93 }
View Code

 

 

 

2:新建一個單元測試:

 

    @Test
    public void test01() {
        List<Aopi> aopiList = Lists.newArrayList();

        Aopi aopi = new Aopi("1", 1);
        Aopi aop2 = new Aopi("2", 2);
        Aopi aop3 = new Aopi("3", 3);
        Aopi aop4 = new Aopi("4", 4);

        aopiList.addAll(Arrays.asList(aopi, aop2, aop3, aop4));

        //第一種方式
        aopiList.forEach(item -> item.setName(item.getName() + "_test"));
        System.out.println(
                aopiList.stream().min((o1, o2) -> {
                    if (Objects.equals(o1.getAge(), o2.getAge()))
                        return 0;
                    return o1.getAge() > o2.getAge() ? 1 : -1;
                }).get().toString()
        );

        System.out.println("zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz");

        //第二種方式
        System.out.println(
                aopiList.stream().peek(item -> item.setName(item.getName() + "_test")).min((o1, o2) -> {
                    if (Objects.equals(o1.getAge(), o2.getAge()))
                        return 0;
                    return o1.getAge() > o2.getAge() ? 1 : -1;
                }).get().toString()
        );

    }

 

notice1:測試第一種方式註釋掉第二種,反之亦如此

notice2:list.stream().foreach  ->  list.foreach()

 

 

3:看測試結果:

第一種測試結果:

 

第二種測試結果:

 

 

結論:

(1):使用stream.foreach也可以更改list中的每個item的內部屬性值等等,但是要進行“二次流處理”,才能得到list中最小的item(根據age篩選)

(2):stream.peek比stream.foreach()可以跟直接拿到最小的item(根據age篩選)

 

原因:

(1):stream.foreach的操作是void的,除了更改屬性值還可以進行其他操作等。因此要做“二次流處理”。

    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

(1):stream.peek的操作是返回一個新的stream的,且設計的初衷是用來debug調試的,因此使用steam.peek()必須對流進行一次處理再產生一個新的stream。

    /**
     * Returns a stream consisting of the elements of this stream, additionally
     * performing the provided action on each element as elements are consumed
     * from the resulting stream.
     *
     * <p>This is an <a href="package-summary.html#StreamOps">intermediate
     * operation</a>.
     *
     * <p>For parallel stream pipelines, the action may be called at
     * whatever time and in whatever thread the element is made available by the
     * upstream operation.  If the action modifies shared state,
     * it is responsible for providing the required synchronization.
     *
     * @apiNote This method exists mainly to support debugging, where you want
     * to see the elements as they flow past a certain point in a pipeline:
     * <pre>{@code
     *     Stream.of("one", "two", "three", "four")
     *         .filter(e -> e.length() > 3)
     *         .peek(e -> System.out.println("Filtered value: " + e))
     *         .map(String::toUpperCase)
     *         .peek(e -> System.out.println("Mapped value: " + e))
     *         .collect(Collectors.toList());
     * }</pre>
     *
     * @param action a <a href="package-summary.html#NonInterference">
     *                 non-interfering</a> action to perform on the elements as
     *                 they are consumed from the stream
     * @return the new stream
     */
    Stream<T> peek(Consumer<? super T> action);

 

bye~^_^

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章