java8stream组装map_Java8Stream的flatmap方法使用

stream中的flatmap是stream的一种中间操作,它和stream的map一样,是一种收集类型的stream中间操作,但是与map不同的是,它可以对stream流中单个元素再进行拆分(切片),从另一种角度上说,使用了它,就是使用了双重for循环。

查看Stream源码中flatmap的方法定义:

Stream flatMap(Function super T, ? extends Stream extends R>> mapper)

从方法的定义可以看出,其入参是一个函数式接口,该接口的返回类型应该是Stream< ? extends R > 类型的。

从实际需求中查看如何使用flatmap:

需求:有一个补习学校,其中有若干老师教学若干门课程,现在学校有关于数学教学的通知要传达给所有学数学的学生家长,将电子邮件发送到他们的邮箱中。

注意:一个老师可以教学多个科目,一个老师可以教学多个学生,一个学生可以报名多个科目,一个学生可以有多个家长。

数据结构(均省略get/set, toString ,构造器):

//老师

public classTeacher {privateString id;privateString name;privateString subject;

}//学生

public classStudent {privateString id;privateString name;privateString techId;//重写hashCode及equals方法(id及name相同就为同一个学生)

}//家长

public classParents {privateString id;privateString name;privateString chirldId;privateString email;

}//课程

public enumSubject {privateString value;privateString desc;

Subject(String value, String desc) {this.value =value;this.desc =desc;

}

Math("1", "数学"),

Chinese("2", "汉语"),

Music("3", "音乐"),

English("4", "英语");

}

实际上的处理也比较简单:

1、找出教学科目为“数学”的老师;

2、找到这些老师对应的学生;

3、根据学生找到对应的家长。

直接贴代码:

public classTest {//模拟数据

public static Student s1 = new Student("1", "zhangsan", "001");public static Student s2 = new Student("2", "lisi", "001");public static Student s3 = new Student("3", "wangwu", "001");public static Student s4 = new Student("4", "zhaoliu", "001");public static Student s5 = new Student("6", "tianqi", "001");public static Student s6 = new Student("6", "tianqi", "002");public static Student s7 = new Student("6", "tianqi", "003");public static Teacher t1 = new Teacher("001", "xiaoming", Subject.Math.getValue());public static Teacher t2 = new Teacher("002", "lihua", Subject.Music.getValue());public static Teacher t3 = new Teacher("003", "hanmeimei", Subject.Math.getValue());public static Teacher t4 = new Teacher("004", "lihua", Subject.English.getValue());public static List stus = new ArrayList<>();public static List teacs = new ArrayList<>();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);

}public static voidmain(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 ->{

Parents p= newParents();

p.setId(UUID.randomUUID().toString());

p.setChirldId(s.getId());

p.setName(s.getName().toUpperCase()+ "‘s Parent");

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‘s Parent‘, chirldId=‘2‘, telNo=‘844668@qq.com‘}

Parents{id=‘7f0b92f5-872d-4671-982d-ef1b48840ce3‘, name=‘WANGWU‘s Parent‘, chirldId=‘3‘, telNo=‘563932@qq.com‘}

Parents{id=‘c318bffd-8c6d-4849-8109-9c686c97fb77‘, name=‘ZHAOLIU‘s Parent‘, chirldId=‘4‘, telNo=‘108022@qq.com‘}

Parents{id=‘a4ff1bbc-c9b6-4ad2-872c-f4df670c7bb6‘, name=‘TIANQI‘s Parent‘, chirldId=‘6‘, telNo=‘658956@qq.com‘}

如果不使用stream,写该部分代码的效果,可能还有优化的空间,但是不够使用stream处理方式更为简洁,方便:

public classTest {public static voidmain(String[] args) {

List pars = new ArrayList<>();

Set targetStudents = new HashSet<>();for(Teacher t : teacs) {if(t.getSubject().equals(Subject.Math.getValue())) {for(Student s : stus) {if(s.getTechId().equals(t.getId())) {

targetStudents.add(s);

}

}

}

}for(Student s : targetStudents) {

Parents p= newParents();

p.setId(UUID.randomUUID().toString());

p.setChirldId(s.getId());

p.setName(s.getName().toUpperCase()+ "‘s Parent");

p.setEmail((int) (Math.random() * 1000000) + "@qq.com");

pars.add(p);

}for(Parents p : pars) {

System.out.println(p);

}

}

}

再去看stream中的flatmap方法,它的作用就和他的名字flat一样,对于调用flatmap的流的每一个元素,执行flatmap入参中的函数式方法,由于该函数式方法必须返回一个stream类型的流,这样对于调用flatmap的操作来说,就收集了另一种类型()的流,并在后续的操作中将类型进行合并,最终产生一个stream的流,而不是一个stream>类型的流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值