关于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~^_^

 

转载于:https://www.cnblogs.com/zgq7/p/11125419.html

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
stream.peek方法的作用是在流的每个元素上执行指定的操作,在不修改流中元素的情况下返回一个新的流。它接受一个Consumer类型的参数,该参数指定了要执行的操作。在中间操作中使用peek方法可以方便地对流进行调试,了解每个操作之前和操作之后的中间值。 在引用的代码中,虽然调用了stream.peek(System.out::println),但没有任何输出。这是因为peek方法是一个中间操作,它只会在终止操作被调用时才会执行。在代码中,并没有调用任何终止操作,所以没有输出。如果想要输出流中的值,可以在peek方法后添加一个终止操作,例如forEach方法来打印出流中的元素。 下面是修改后的代码示例: ```java public class PeekTestTwo { public static void main(String[] args) { Stream<Integer> stream = Arrays.asList(4, 7, 9, 11, 12).stream(); stream.peek(System.out::println).forEach(System.out::println); } } ``` 现在,当运行这段代码时,会先输出每个元素的值,然后再打印出流中的元素值。这是因为在peek方法中,我们指定了打印每个元素的操作,而在forEach方法中,我们又指定了打印流中元素的操作。这样就能够看到每个操作之前和操作之后的中间值。 请注意,peek方法不会改变流中的元素,它只是提供了一种便捷的方式来查看流中每个元素的值。要改变流中的元素,需要使用其他的中间操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值