为了账号安全,请及时绑定邮箱和手机立即绑定

如何使用Stream过滤嵌套对象?

如何使用Stream过滤嵌套对象?

ABOUTYOU 2021-09-15 17:08:15
我想使用 Stream API 过滤嵌套对象。问题是嵌套类太多,使用下面的方法我写了太多重复的代码。有没有办法在没有重复代码的情况下处理这个流?public class Country{    Map<String, City> cities;}public class City{    Map<String, School> schools;}public class School{    String name;    String address;    Model model;}public class Model{    String name;    Teacher teacher;}public class Teacher{    String name;    String id;}我的直播;country.getCities().values().stream().foreach(     (City city) ->         city.getSchools()             .entrySet()                   .stream()             .filter(schoolEntry -> schoolEntry.getValue().getName().equals("test"))              .filter(schoolEntry -> schoolEntry.getValue().getModel().getName().equals("test2"))             .filter(schoolEntry -> schoolEntry.getValue().getModel().getTeacher().getName().equals("test2"))             .foreach(schoolEntry -> {                  String schoolKey = schoolEntry.getKey();                  resultList.put(schoolKey, schoolEntry.getValue().getModel().getTeacher().getId());              })    );
查看完整描述

3 回答

?
HUWWW

TA贡献1874条经验 获得超12个赞

您可以定义一种方法来使用它Predicate来过滤学校。


public static boolean matches(School school, String schoolName, String modelName, String teacherId) {

    return school.getName().equals(schoolName) 

            && school.getModel().getName().equals(modelName) 

            && school.getModel().getTeacher().getId().equals(teacherId);

}

将此应用于流:


public static Map<String, String> getSchoolAndTeacherFrom(Country country, Predicate<School> schoolWithModelAndTeacher) {

    return country.getCities().values().stream()

            .flatMap(c -> c.getSchools().entrySet().stream())

            .filter(s -> schoolWithModelAndTeacher.test(s.getValue()))

            .collect(Collectors.toMap(Entry::getKey, schoolEntry -> schoolEntry.getValue().getModel().getTeacher().getId()));

}

像这样使用:


    Country country = <county>

    Predicate<School> schoolWithModelAndTeacher = school -> matches(school, "test1", "test2", "test2");

    getSchoolAndTeacherFrom(country, schoolWithModelAndTeacher);

一些进一步的想法:


如果地图schools使用School.getName()的密钥,那么我们可以这样写:


public static Map<String, String> getSchoolAndTeacherFrom(Country country, Predicate<School> schoolWithModelAndTeacher) {

    return country.getCities().values().stream()

            .flatMap(city -> city.getSchools().values().stream())

            .filter(schoolWithModelAndTeacher::test)

            .collect(Collectors.toMap(School::getName, school -> school.getModel().getTeacher().getId()));

}

假设一个国家的学校名称和教师 ID 是唯一的(而模型名称是常见的),则过滤将导致单个值(如果有)。但是就不需要Mapas 结果类型了。类型的结果Entry<String String>会做到这一点。

如果谓词的参数仍然是已知的(学校、模型、教师),那么整个事情只是一个问题,即在某个国家/地区是否有给定模型的给定学校的给定教师。然后我们可以写得更短:


public static boolean isMatchingSchoolInCountryPresent(Country country, Predicate<School> schoolWithModelAndTeacher) {

    return country.getCities().values().stream()

            .flatMap(c -> c.getSchools().values().stream())

            .anyMatch(schoolWithModelAndTeacher::test);

}


查看完整回答
反对 回复 2021-09-15
  • 3 回答
  • 0 关注
  • 349 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信