Java8 流式API
为什么引入流式API
在java中对于数据的操作常常是借助数据库来做到的,java自带的集合操作方法是不能对于大数据量的数据进行各种操作,常常要做的就是遍历再遍历,另外java中集合操作无法支持并行执行,流式API的出现可以发挥多核处理器的优势
使用
构建stream
静态工厂方法(Stream)
of方法
方法参数也可以将数组或者集合,转换为流,Java中流对象只有IntStream,DoubleStream和StringStream1
IntStream intStream = of(1, 2, 3);
generate方法
该方法用于随机数产生,或者常量Stream等,返回无限长度的流最好借助lambda表达式
1
2Stream<Double> stream2 = Stream.generate(() -> Math.random());
Stream<Double> stream3 = Stream.generate(Math::random);iterate方法
:1
Stream.iterate(0, x -> x++);
empty方法
:返回一个一个空的流1
Stream<Object> empty = Stream.empty();
集合和数组调用stream()方法
stream
的操作
流的操作分为两种:
Intermediate
:map
、filter
、distinct
、sorted
、peek
、limit
、skip
、parallel
、sequential
Terminal
:forEach
、forEachOrdered
、toArray
、reduce
、collect
、min
、max
、count
、iterator
Intermediate中间操作不会导致流的消失,返回值为stream,Terminal操作结束后流即消失了
stream
使用示例
demo数据如下:
1 | List<User> list = new ArrayList<>(); |
map:输入流中元素执行操作后一一映射输出流的元素,这个经常会用到,尤其是再将对象的集合转变为对象中属性的集合,另外map
经常和reduce
操作混合使用来归并数据
1 | List<Integer> ageList1 = list.stream().map(x -> x.getAge()).collect(Collectors.toList()); |
filter:条件为布尔值,将满足条件的过滤出来
1 | List<User> collect = list.stream().filter(x -> x.getAge() > 0).collect(Collectors.toList()); |
distinct:去重,就可以看作放到set集合之中,但有序
1 | list.stream().distinct().forEach(x-> System.out.println(x)); |
sorted:排序,基本数据类型是可以比较的(我没测全),对象直接比较会报错,需要自己实现比较器
1 | List list1 = new ArrayList<>(); |
peek:用的不多,一般用来查看元素和打印元素,他和foreach的区别在于它只是中间操作,流依然存在
1 | List<User> userList1 = list.stream().distinct().peek(x -> System.out.println(x)).collect(Collectors.toList()); |
limit/skip:截断流,区别在于limit
截取前几个元素返回流,而skip
是跳过前几个元素返回流
1 | list.stream().limit(6).skip(3).forEach(x -> System.out.println(x.getName())); |
parallel/sequential:并行流和串行流的互转,parallel
将串行流转换为并行流,sequential
将并行流转换为串行流,并行流不在乎保持最终的次序,所以更加快,但有时候顺序可能有误,串行流会维持最初的顺序,我用的不多
forEach:和peek类似只是为终端操作
forEachOrdered:foreach+sorted
toArray:归并流为数组
reduce:可以理解为将初始值,按照一定的规则,对每一个流中的元素迭代的执行,直至到最后,使用非常广泛,它的完整版接受三个参数:reduce(identity, accumulator, combiner)
,第一个参数为初始值,第二个为迭代操作,第三个为多个迭代结果的合并操作,另外两个方法都是其简略版,(accumulator
)和(identity
,accumulator
),事实上min
,max
,count
都是reduce
操作,值得注意的是combiner的作用是将并行流的处理结果归并时的执行策略,我基本不用,也不说了,免得写错了
1 | //求和(因为没有初始值,可能出现null,所以返回的optional) |
max/min:如上所述,一种特殊的reduce操作,取出最大或者最小值,用法较简单
match:返回值为布尔类型,它包括有allMatch(全部满足返回true),anyMatch(任意一个满足返回true),noneMatch(没有一个满足返回true)
collect:它和reduce一样重要,将流的结果处理为定义的类型,继续介绍完整版方法collect(supplier, accumulator, combiner)
对于list而言,第一个为想要获取的结果类型,使用new语法获取对象;第二个为将当前元素添加到目标中的方法;第三个为将修改后的对象转为自定义对象方法;
1 | //重载版 |
对于map集合而言,第一个参数为key的映射,第二个为value的映射,第三个为key相同时的处理策略
1 | list.stream().collect(Collectors.toMap(User::getName, User::getAge, (K1, K2) -> K1)); |
进阶用法
直接分组
1 | Map<String,List<User>>collect=list.stream().collect(Collectors.groupingBy(x->x.getName())); |
按照姓名分组计数求和
1 | //这是个重载的方法 |
collectAndThen迭代生成流的处理:它比前者要多出一个流处理位置
1 | //组内top值 |
相关
Java8 流式API