Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
流的API较多,有一些使用起来还是有一定的理解成本。为了方便大家理解,本文通过具体的示例进行总结。欢迎大家讨论交流。
下面是例子中的对象,不考虑字段的实际意义,只是为了方便演示。
public class UserPo {
private Long id;
private String name;
private Integer age;
private Long imageFileId1;
private Long imageFileId2;
//... 省略 get,set,hashCode和equals
}
UserPo userPo1=new UserPo(1L,"user1",10,100L,101L);
UserPo userPo2=new UserPo(2L,"user2",20,200L,201L);
List<UserPo> userPoList= Arrays.asList(userPo1,userPo2);
生成流
这里只介绍两种方式:手动创建,使用集合创建
1、手动创建
Stream<UserPo> userPoStream = Stream.of(userPo1,userPo2);
2、集合创建
Stream<UserPo> userPoStream = userPoList.stream();
map操作
map可以理解为转换操作,对每一个对象进行转换。
//提取对象中的某一个属性值的集合(把每一个对象转化为某一个属性值)
Set<String> nameSet = userPoList.stream().
map(e -> e.getName()).collect(Collectors.toSet());
flatMap操作
flatmap一直有点不太好理解。
先看一个具体的问题,上面map操作中,生成了包含所有名称的nameSet集合。
如果要获取对象中的所有的fileId,每个对象中包含imageFileId1,imageFileId2。最终的结果应该是生成包含了{100,101,200,201}四个元素的集合。
Set<Long> fileIdSet = userPoList.stream().
flatMap(e -> Stream.of(e.getImageFileId1(), e.getImageFileId2())).
collect(Collectors.toSet());
flatMap方法接受一个lambda表达式函数, 函数的返回值必须也是一个stream类型,flatMap方法最终会把所有返回的stream合并。
list转map
把userPoList ==> map<key/*id*/,value/*UserPo*/>,这也是一个经常使用的操作
//如果key重复,则仅保留第一个userPo
Map<Long, UserPo> userPoMap = userPoList.stream().
collect(Collectors.toMap(UserPo::getId, e -> e, (v1, v2) -> v1));
把userPoList ==> map<key/*id*/,List<value>/*UserPo*/>,聚合操作,按照某一个属性值。例如把按照年龄进行归类
Map<Integer, List<UserPo>> ageMap =userPoList.stream().
collect(Collectors.groupingBy(UserPo::getAge));
sorted操作
排序也是一个经常使用的操作
List<UserPo> ageSort = userPoList.stream().
sorted(Comparator.comparing(UserPo::getAge)).
collect(Collectors.toList());
filter操作
filter过滤不符合条件的对象
Set<UserPo> filterAge = userPoList.stream().
filter(userPo -> userPo.getAge() > 10).
collect(Collectors.toSet());