Stream的reduce的使用

Stream的reduce的使用概述  reduce的意思的减少,缩小;但是这个方法的使用更像是流元素的累积操作,因为这个方法会将流中所有的元素经过累积操作之后返回。  在有一个重点,就是什么是累积操作?这个东西怎么解释呢,就是一个对象数据和流中的第一元素进行操作,然后返回,之后被返回的这个数据回和第二个流元素进行操作,然后返回,之后被返回的数据再和第三个流元素进行操作,然后返回,……,往复进行,直到最后一个元素,之后将操作后的数据返回给用户。这个就是累积操作。(这个属于个人理解,如果不适,请指正)  再strem类两种reduec

大家好,欢迎来到IT知识分享网。Stream的reduce的使用"

概述

  reduce的意思的减少,缩小;但是这个方法的使用更像是流元素的累积操作,因为这个方法会将流中所有的元素经过累积操作之后返回。

  这有一个重点,就是什么是累积操作?这个东西怎么解释呢,就是一个对象数据和流中的第一元素进行操作,然后返回,之后被返回的这个数据回和第二个流元素进行操作,然后返回,之后被返回的数据再和第三个流元素进行操作,然后返回,……,往复进行,直到最后一个元素,之后将操作后的数据返回给用户。这个就是累积操作。(这个属于个人理解,如果不适,请指正)

  在strem类中reduece方法给出了三种,但是这三种是一样的,只是功能扩展度是不一样的。三个方法如下:

1. Optional<T> reduce(BinaryOperator<T> accumulator);
2. T reduce(T identity, BinaryOperator<T> accumulator);
3. <U> U reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner);

注意:2是1的功能扩展,3是1、2的功能扩展。但是1,2不能使用并行流(经过测试会出现错误),3可以使用并行流。(为什么1、2不能使用并行流呢?后面说)

参数说明

1. Optional reduce(BinaryOperator accumulator);

  这个总共就一个参数,这个参数的名称accumulator(累加器),它的类型是一个函数式接口,这个接口是继承了BiFunction<T,U,R>,实现这个接口有两个输入,一个T类型,一个U类型,返回值是R类型。

  这reduce里面T表示的是累加对象(累积操作对象),U表示的就是流元素对象,而R就是要返回的结果。但是 BinaryOperator 类型实现了 BiFunction<T,U,R> 之后只给了一个类型T,所以这里的T、U、R都是流元素对象类型(这里有一个问题就是这个累加对象参数的初始值是什么,这里默认是流的第一个元素,具体看下面的第二个方法)。案例如下:

// 这里的acc+i的值都是下一次循环的acc
Optional<Integer> sum = Stream.of(1, 2, 3).reduce((acc, i) -> acc + i);
// 6
System.err.println(sum.get()); 

2. T reduce(T identity, BinaryOperator accumulator);

  如果你把上面的那个函数看明白了,这个也就好理解了,因为这个方法只是比上面的方法多了一个参数 T identity ,而且这个参数的类型已经给你规定好了就是流元素的类型。

  这个方法有两个参数,第一个是已经说明,第二个和上面方法的解释是一摸一样的,那么第一个参数其实就是累加对象参数的初始值(必须是流元素类型),也就是说你可以自定义一个初始对象然后和流里面的每个元素进行累积操作。案例如下:

// 这里的acc+i的值都是下一次循环的acc
Integer sum = Stream.of(1, 2, 3).reduce(Integer.valueOf(1), (acc, i) -> acc + i);
// 7   初始化值是1
System.err.println(sum);

3. U reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator combiner)

  这个方法有三个参数,前两个参数和第二个方法的是差不多的,唯一的区别就是对第二个方法的缺点进行了改进,为什么说是缺点呢,因为第二个方法限制了初始值和返回值都必须是流元素类型,但是这个方法可以然后我们自定义初始值和返回值的类型了,这个就极大的扩展了方法的可用性(有点类似collect的方法)。

  第三个参数combiner,就是用来合并的,也是前面提到的,为什么第三个方法能够使用并行流的重要原因。因为我们使用并行流的时候会将流元素分成n组再各自的线程中执行,执行完成之后结果在各个线程中如果你没有合并返回的结果是不完整的,所以只有有合并参数的第三个方法可以使用并行流。同时反过来说明只有只用了并行流这个参数才有执行的意义。

String sum = Stream.of(1, 2, 3).reduce(String.valueOf("1"),
                (acc, i) -> String.valueOf(Integer.valueOf(acc) + i),
                (acc1, acc2) -> String.valueOf(Integer.valueOf(acc1) + Integer.valueOf(acc2)));
// 7
System.err.println(sum);

  注: 这里有一个特别需要注意的地方,就是使用并行流。当你使用第三个方法并且使用的是并行流的时候要特别的注意,初始化对象会使用在并行的各个线程中而且指向的是同一个对象,所以使用和返回的时候要特别的注意这个初始化对象,否则就会出现如下的问题:

String sum = Stream.of(1, 2, 3).parallel().reduce(String.valueOf("1"),
                (acc, i) -> String.valueOf(Integer.valueOf(acc) + i),
                (acc1, acc2) -> String.valueOf(Integer.valueOf(acc1) + Integer.valueOf(acc2)));
// 9 把上面的的那个案例有单行流改成了并行流,这个结果是不一定的,可能8可能7,看并行流数量
System.err.println(sum);

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/11377.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信