Java8 Stream flatmap中间操作用法解析
stream中的flatmap是stream的一种中间操作,它和stream的map一样,是一种收集类型的stream中间操作,但是与map不同的是,它可以对stream流中单个元素再进行拆分(切片),从另一种角度上说,使用了它,就是使用了双重for循环。
查看Stream源码中flatmap的方法定义:
从方法的定义可以看出,其入参是一个函数式接口,该接口的返回类型应该是Stream类型的。
从实际需求中查看如何使用flatmap:
需求:有一个补习学校,其中有若干老师教学若干门课程,现在学校有关于数学教学的通知要传达给所有学数学的学生家长,将电子邮件发送到他们的邮箱中。
注意:一个老师可以教学多个科目,一个老师可以教学多个学生,一个学生可以报名多个科目,一个学生可以有多个家长。
数据结构(均省略get/set,toString,构造器):
//老师
publicclassTeacher{
privateStringid;
privateStringname;
privateStringsubject;
}
//学生
publicclassStudent{
privateStringid;
privateStringname;
privateStringtechId;
//重写hashCode及equals方法(id及name相同就为同一个学生)
}
//家长
publicclassParents{
privateStringid;
privateStringname;
privateStringchirldId;
privateStringemail;
}
//课程
publicenumSubject{
privateStringvalue;
privateStringdesc;
Subject(Stringvalue,Stringdesc){
this.value=value;
this.desc=desc;
}
Math("1","数学"),
Chinese("2","汉语"),
Music("3","音乐"),
English("4","英语");
}
实际上的处理也比较简单:
1、找出教学科目为“数学”的老师;
2、找到这些老师对应的学生;
3、根据学生找到对应的家长。
直接贴代码:
publicclassTest{
//模拟数据
publicstaticStudents1=newStudent("1","zhangsan","001");
publicstaticStudents2=newStudent("2","lisi","001");
publicstaticStudents3=newStudent("3","wangwu","001");
publicstaticStudents4=newStudent("4","zhaoliu","001");
publicstaticStudents5=newStudent("6","tianqi","001");
publicstaticStudents6=newStudent("6","tianqi","002");
publicstaticStudents7=newStudent("6","tianqi","003");
publicstaticTeachert1=newTeacher("001","xiaoming",Subject.Math.getValue());
publicstaticTeachert2=newTeacher("002","lihua",Subject.Music.getValue());
publicstaticTeachert3=newTeacher("003","hanmeimei",Subject.Math.getValue());
publicstaticTeachert4=newTeacher("004","lihua",Subject.English.getValue());
publicstaticListstus=newArrayList<>();
publicstaticListteacs=newArrayList<>();
static{
stus.add(s1);
stus.add(s2);
stus.add(s3);
stus.add(s4);
stus.add(s5);
stus.add(s6);
stus.add(s7);
teacs.add(t1);
teacs.add(t2);
teacs.add(t3);
teacs.add(t4);
}
publicstaticvoidmain(String[]args){
//找到所有数学老师的学生的家长的电话,并找他们开家长会
Listcollect=teacs.stream()
//过滤数学老师
.filter(t->Subject.Math.getValue().equals(t.getSubject()))
//通过老师找学生
.flatMap(t->stus.stream().filter(s->s.getTechId().equals(t.getId())))
//过滤重复的学生(使用student的equals和hashCode方法)
.distinct()
//通过学生找家长(这里就简化为创建家长对象)
.map(s->{
Parentsp=newParents();
p.setId(UUID.randomUUID().toString());
p.setChirldId(s.getId());
p.setName(s.getName().toUpperCase()+"'sParent");
p.setEmail((int)(Math.random()*1000000)+"@qq.com");
returnp;
})
.collect(Collectors.toList());
//打印到控制台看看
collect.stream()
.forEach(System.out::println);
}
}
运行结果:
Parents{id='3d9312eb-0df5-4ec6-998f-94a32c2253b4',name='LISI'sParent',chirldId='2',telNo='844668@qq.com'}
Parents{id='7f0b92f5-872d-4671-982d-ef1b48840ce3',name='WANGWU'sParent',chirldId='3',telNo='563932@qq.com'}
Parents{id='c318bffd-8c6d-4849-8109-9c686c97fb77',name='ZHAOLIU'sParent',chirldId='4',telNo='108022@qq.com'}
Parents{id='a4ff1bbc-c9b6-4ad2-872c-f4df670c7bb6',name='TIANQI'sParent',chirldId='6',telNo='658956@qq.com'}
如果不使用stream,写该部分代码的效果,可能还有优化的空间,但是不够使用stream处理方式更为简洁,方便:
publicclassTest{
publicstaticvoidmain(String[]args){
Listpars=newArrayList<>();
SettargetStudents=newHashSet<>();
for(Teachert:teacs){
if(t.getSubject().equals(Subject.Math.getValue())){
for(Students:stus){
if(s.getTechId().equals(t.getId())){
targetStudents.add(s);
}
}
}
}
for(Students:targetStudents){
Parentsp=newParents();
p.setId(UUID.randomUUID().toString());
p.setChirldId(s.getId());
p.setName(s.getName().toUpperCase()+"'sParent");
p.setEmail((int)(Math.random()*1000000)+"@qq.com");
pars.add(p);
}
for(Parentsp:pars){
System.out.println(p);
}
}
}
再去看stream中的flatmap方法,它的作用就和他的名字flat一样,对于调用flatmap的流的每一个元素,执行flatmap入参中的函数式方法,由于该函数式方法必须返回一个stream
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。