今天下了JDK 8 EA 尝尝鲜
摸了好久才摸懂 一些地方 写写文章分享下经验 如有说错欢迎打脸
reduce的操作有点麻烦 所以这里就专门说一下
如有说错欢迎打脸...
因为java是静态语言所以一些地方自然不如动态语言方便
比如说我这里有个要求 把0-99的List打印成String输出(当然直接用for也可以啦)
用groovy的话 代码很简单:
def list=0..<100 def sb=list.inject(new StringBuffer(),{result,element -> result.append("${element} ")})
最后也会用java中 stream的reduce说一遍
开始...
而java中的reduce操作有三个:
- 一个参数的
- 两个参数的
- 三个参数的_(:3」∠)_
一个简单是实例 完成累加的操作(当然用mapToInt然后再用sum更好,这里说明用):
public static void main(String[] args){ List<Integer> list=new ArrayList<Integer>(); for(int i=0;i<100;i++){ list.add(Integer.valueOf(i)); } System.out.println(list.stream().reduce( (result,element)-> result=result+element)); System.out.println(list.stream().reduce( 0, (result,element)-> result=result+element)); System.out.println(list.stream().reduce( 0, (result,element)-> result=result+element ,(u,t) -> t)); }
结果:
在实现中
一个参数是这样实现(近似的实现)的:
boolean foundAny = false; T result = null; for (T element : this stream) { if (!foundAny) { foundAny = true; result = element; } else result = accumulator.apply(result, element); } return foundAny ? Optional.of(result) : Optional.empty();
实现很简单 初始的result是stream中的某一个值(实际中不是顺序执行的) 之后执行你给的函数就可以了(请把accumulator.apply(result,element) 用自己的函数代替 这里是 result=result+element;
从这里也提醒了函数中参数的位置 聚合用的result是第一个参数 遍历的元素放在第二个参数里
二个参数的也同理:
T result = identity; for (T element : this stream) result = accumulator.apply(result, element) return result;
因为result用的是自定义的值(要符合泛型的要求) 所以代码短一些
三个参数的 对初始值没有泛型的要求:
U result = identity; for (T element : this stream) result = accumulator.apply(result, element) return result;
看起来和第二个除了在泛型的要求上不一样之外 也没其他什么 但他有个要求
对于第二个函数有限制:
必须满足
combiner.apply(u, accumulator.apply(identity, t)) == accumulator.apply(u, t)
但实际使用的时候感觉怪怪的...因为即使有打印信息 并不会有任何输出 但如果这个函数没有返回任何东西无法通过编译.. 实际中直接返回u或者t就可以了(这里有人知道为什么吗..求解),但为了符合以上这个规定,两个函数写得一样好像也没关系.
只有第三个参数的reduce是不受流的类型限制的 也就是可以返回任意类型的数据 所以三个参数的那个实用性大一点(应该...)
现在回到刚开始的问题里
给出代码:
import java.util.*; import java.util.concurrent.*; import java.util.stream.*; public class Test4{ public static void main(String[] args){ List<Integer> list=new ArrayList<Integer>(); for(int i=0;i<100;i++){ list.add(Integer.valueOf(i)); } System.out.println(list.stream().reduce( new StringBuilder(), (result,element)-> result=result.append(element) ,(u,t) -> u=u.append(t))); //这个地方 返回 u或者t也是可以的 运行没错 } }