On the difference between stream.foreach() and stream.peek().

Keywords: PHP Attribute

Change thinking comes from daily work, so remember this experience.

 

Thinking: how to quickly change the internal attribute value of each item in the list and perform other fluid operations?

Here's a test: how to get the object in the list according to the minimum value of a property

 

1: create any new test 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      * Full name
15      */
16     private String name;
17 
18     /**
19      * Age
20      */
21     private Integer age;
22 
23     /**
24      * Get id
25      *
26      * @return id - id
27      */
28     public Integer getId() {
29         return id;
30     }
31 
32     /**
33      * Set id
34      *
35      * @param id id
36      */
37     public void setId(Integer id) {
38         this.id = id;
39     }
40 
41     /**
42      * Get name
43      *
44      * @return name - Full name
45      */
46     public String getName() {
47         return name;
48     }
49 
50     /**
51      * Set name
52      *
53      * @param name Full name
54      */
55     public void setName(String name) {
56         this.name = name;
57     }
58 
59     /**
60      * Age of acquisition
61      *
62      * @return age - Age
63      */
64     public Integer getAge() {
65         return age;
66     }
67 
68     /**
69      * Age setting
70      *
71      * @param age 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 }

 

 

 

2: create a new unit test:

 

    @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));

        //The first way
        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");

        //The second way
        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()
        );

    }

 

Note 1: test the first way to comment out the second way, and vice versa

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

 

 

3. See the test results:

The first test result:

 

The second test result:

 

 

Conclusion:

(1): using stream.foreach, you can also change the internal property value of each item in the list, etc., but you need to perform "secondary flow processing" to get the smallest item in the list (filter according to age).

(2): stream.peek can get the smallest item directly compared with stream.foreach().

 

Reason:

(1): the operation of stream.foreach is void. In addition to changing the property value, other operations can also be performed. So we need to do "secondary flow processing".

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

(1): the operation of stream.peek returns a new stream, and the original intention of the design is to debug, so using stream. Peek() must process the stream once and then generate a new 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~^_^

Posted by alasxdair on Thu, 31 Oct 2019 01:39:54 -0700