之前介绍过stream的部分操作,感觉写的太简单的,示例也太少了,这次再次整理了stream类下大家在工作中会常用的方法。
Stream流非IO流,Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk data operation)。然后使用lambda表达式可以让你的代码写的更少,做的更多!
** 聚合操作**
大家在使用数据库的时候都会用到一些聚合函数,例如 avg(),count(),min(),max().但是您的项目经理或许不允许让你在sql中写大量的函数,写过多的逻辑,都是一些简单的sql语句,然后处理数据的逻辑放给代码进行处理,不管你的访问压力大小,让你的sql变简单都是一个很好的习惯,大家以后也要注意下哈。这时候返回的集合数据,就需要处理了,之前的处理方式for循环,然后在每个循环对象内进行逻辑判断。现在jdk8提供了stream流。这样让我们在对集合数据进行去重,过滤,遍历数据都变得方便许多。
** 什么是流**
Stream 不是集合元素,它不是数据结构并不保存数据,它是有关算法和计算的,它更像一个高级版本的 Iterator。原始版本的 Iterator,用户只能显式地一个一个遍历元素并对其执行某些操作;高级版本的 Stream,用户只要给出需要对其包含的元素执行什么操作,比如 “过滤掉长度大于 10 的字符串”、“获取每个字符串的首字母”等,Stream 会隐式地在内部进行遍历,做出相应的数据转换。
Stream 就如同一个迭代器(Iterator),单向,不可往复,数据只能遍历一次,遍历过一次后即用尽了,就好比流水从面前流过,一去不复返。
而和迭代器又不同的是,Stream 可以并行化操作,迭代器只能命令式地、串行化操作。顾名思义,当使用串行方式去遍历时,每个 item 读完后再读下一个 item。而使用并行去遍历时,数据会被分成多个段,其中每一个都在不同的线程中处理,然后将结果一起输出。Stream 的并行操作依赖于 Java7 中引入的 Fork/Join 框架(JSR166y)来拆分任务和加速处理过程。Java 的并行 API 演变历程基本如下:
- 1.0-1.4 中的 java.lang.Thread
- 5.0 中的 java.util.concurrent
- 6.0 中的 Phasers 等
- 7.0 中的 Fork/Join 框架
- 8.0 中的 Lambda
Stream 的另外一大特点是,数据源本身可以是无限的。
下面介绍详细的操作代码
我在工作中常用到对流的操作有filter,map,两种操作filter:过滤,可以在遍历数据的时候在filter写判断条件map:操作,根绝遍历的对象,不需要过滤,只是对每个对象进行处理,比如要返回每个对象的某个字段
List users=new ArrayList<>(); //用户集合中返回userId字段为空的集合 List users1 = users.stream().filter(obj -> obj.getUserId().equals("")).collect(Collectors.toList()); //用户集合中返回userId字段为空的集合中的第二个开始查 返回第一个用户对象 User user = users.stream().filter(obj -> obj.getUserId().equals("")).skip(1).findAny().get(); //用户集合中返回userId字段为空的集合中返回第一个用户对象 User user1 = users.stream().filter(obj -> obj.getUserId().equals("")).findFirst().get(); //用户集合中返回userId字段为空的集合中返回第一个用户对象(串行查询跟上面结果一样,并行查询返回最快回来的那个) User user2 = users.stream().filter(obj -> obj.getUserId().equals("")).findAny().get(); //根据年龄降序排序用户 不加reversed()方法默认升序 List collect = users.stream().sorted(Comparator.comparing(User::getAge).reversed()).collect(Collectors.toList());
排序也支持多条件排序,在第一个排序后面加一个
thenComparing() 即为下一个排序条件
还有distinct()方法去重,不过该方法只适用于基本类型的list。
//返回用户里面年龄大于10岁的用户id List collect3 = collect.stream().filter(obj -> obj.getAge() > 10).map(User::getUserId).collect(Collectors.toList()); //年龄最大的用户是多少岁 Integer integer = users.stream().map(User::getAge).max(Integer::compare).get(); //返回每个用户的用户id List collect1 = users.stream().map(User::getUserId).collect(Collectors.toList()); //转换用户id的值为小写值 List collect2 = collect1.stream().map(String::toLowerCase).collect(Collectors.toList());
当你使用skip(),limit()方法等需要注意数组越界问题,因为有时候你的返回结果是一个空的。
还有对于filter与map同时使用的话记得先用filter再用map方法。
//返回一个map key是年龄 value是该年龄有多少人 Map collect4 = users.stream().collect(groupingBy(User::getAge, counting())); //返回一个map key是年龄 value是属于该年龄的集合 Map> collect5 = users.stream().collect(groupingBy(User::getAge));
groupby后返回一个map也是常用的方法。
over