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);
  • 15
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值