java streamJavaStream中reduce⽅法的使⽤
三种重载的⽅法
第⼀种
Optional<T>reduce(BinaryOperator<T> accumulator);
⽅法接受⼀个BinaryOperator类型的lambada表达式, 常规应⽤⽅法如下:
List<Integer> list = Arrays.asList(1,2,3,4);
int result = list.stream().reduce((a,b)-> a+b).get();
System.out.println(result);
代码实现了对list 中的元素累加。lambada表达式的a参数是表达式的执⾏结果的缓存,也就是表达式这⼀次的执⾏结果会被作为下⼀次执⾏的参数,⽽第⼆个参数b则是依次为stream中每个元素。如果表达式是第⼀次被执⾏,a则是stream中的第⼀个元素。
第⼆种
T reduce(T identity, BinaryOperator<T> accumulator);
⽅法接受⼀个identity和BinaryOperator类型的lambada表达式, 与第⼀个签名的实现的唯⼀区别是它⾸次执⾏时表达式第⼀次参数并不是stream的第⼀个元素,⽽是通过签名的第⼀个参数identity来指定。我们来通过这个签名对之前的求和代码进⾏改进。
List<Integer> list = Arrays.asList(1,2,3,4);
int result = list.stream().reduce(1,(a,b)-> a+b);
System.out.println(result);
其实这两种实现⼏乎差别,第⼀种⽐第⼀种仅仅多了⼀个字定义初始值罢了。 此外,因为存在stream为空的情况,所以第⼀种实现并不直接⽅法计算的结果,⽽是将计算结果⽤Optional来包装,我们可以通过它的get⽅法获得⼀个Integer类型的结果,⽽Integer允许null。第⼆种实现因为允许指定初始值,因此即使stream为空,也不会出现返回结果为null的情况,当stream为空,reduce为直接把初始值返回。
第三种
<U> U reduce(U identity,
BiFunction<U,?super T, U> accumulator,
BinaryOperator<U> combiner);
第三种签名的⽤法相较前两种稍显复杂,犹豫前两种实现有⼀个缺陷,它们的计算结果必须和stream中的元素类型相同,如上⾯的代码⽰例,stream中的类型为int,那么计算结果也必须为int,这导致了灵活性的不⾜,甚⾄⽆法完成某些任务, ⽐⼊我们咬对⼀个⼀系列int值求和,但是求和的结果⽤⼀个int类型已经放不下,必须升级为long类型,此实第三签名就能发挥价值了,它不将执⾏结果与stream中元素的类型绑死。
List<Integer> list = Arrays.asList(Integer.MAX_VALUE,Integer.MAX_VALUE);
long result = list .stream().reduce(0L,(a,b)->  a + b,(a,b)-> null);
System.out.println(result);
注意该⽅法还有第三个参数,⼀个BinaryOperator类型的参数,此参数是⽤来处理多线程中每个线程的结果如何合并的问题。举例将执⾏结果简单相加:
List<Integer> list = Arrays.asList(1,2,3,4);
int result = list.stream().parallel().reduce(1,(a,b)-> a+b,(a, b)-> a+b);
System.out.println(result);
此时的执⾏结果:
居然是14,⽽不是11,说明第三个参数中,将结果简单相加是错误的。前两种⽅法如果使⽤parallel执⾏,那么结果也会是错误的。
原因是什么呢?
推想⼀下⼀下,parallel开启了四个线程进⾏计算分别是
Thread-1:1+1=2
Thread-2:1+2=3
Thread-3:1+3=4
Thread-4:1+4=5
//处理计算结果简单相加
2+3+4+5=14
看到这⾥你应该明⽩出错的原因了,identity(值为1)属性被多加了三次,要解决这个问题也很简单,在两两相加合并结果的时候减去⼀个identity(值为1)即可:
List<Integer> list = Arrays.asList(1,2,3,4);
int result = list.stream().parallel().reduce(1,(a,b)-> a+b,(a, b)-> a+b-1);
System.out.println(result);
运⾏结果:
可以推想此时的运⾏流程⼤致为:
Thread-1:1+1=2
Thread-2:1+2=3
Thread-3:1+3=4
Thread-4:1+4=5
//处理计算结果两两合并时减1
2+3-1=4
4+4-1=7
7+5-1=11
计算结果为11,正确

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。