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<>(); publicstaticList teacs=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){ //找到所有数学老师的学生的家长的电话,并找他们开家长会 List collect=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<>(); Set targetStudents=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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。