【问题标题】:Filtering Java Nested List过滤 Java 嵌套列表
【发布时间】:2022-01-26 22:34:37
【问题描述】:

我有一个包含班级的学校列表,其中还包含学生的班级列表和学生也是另一个列表。我想应用两个嵌套过滤器,首先将检查是否有任何班级有一个空的学生列表,第二个过滤器用于检查学校是否有任何空班级列表,最后它应该返回列表,但我不能应用两个过滤器嵌套时,我不断收到语法错误。我对流 api 有点陌生。

result = result.stream()
          .filter(school -> school.getSchoolClassList().stream()
                    .filter(schoolClass-> schoolClass.getStudentList().stream()
                    .anyMatch(schoolClass-> schoolClass.getStudentList().size() > 0))
          .anyMatch(school -> school.getSchoolClassList().size() > 0))
          .collect(Collectors.toList());

【问题讨论】:

  • 只需使用.filter(cls-> cls.getStudentList().size() > 0),无需流式传输该列表。
  • 很抱歉,结果并不是我真正想要的。我想过滤班级和学校数组。

标签: java list filtering lightweight-stream-api


【解决方案1】:

您可能想要添加生成的语法错误。但是,正如我首先看到的那样,您使用 class 作为标识符,而它实际上是 Java 编程语言中的保留关键字。考虑将标识符重命名为 schoolClass

【讨论】:

  • 先举个例子,anyMatch 方法说不能解析学生类型的 getStudentList() 方法。我以示例代码为例,这个任务是我实习的公司给我的
【解决方案2】:

我不确定我是否理解正确,但据我所知,您希望获得所有有空班或没有学生的学校。

您可以做的是在流之外定义谓词。

Predicate<School> empty_students_filter = school ->
    school.getSchoolClassList().stream().map(SchoolClass::getStudentList).anyMatch(List::isEmpty);

Predicate<School> empty_classes_filter = school -> school.getSchoolClassList().isEmpty();

然后你可以在你的过滤方法中使用谓词并将它们与 Predicate.or() 结合起来:

List<School> schools_with_no_or_empty_classes = 
    schools.stream()
           .filter(empty_classes_filter.or(empty_students_filter))
           .collect(Collectors.toList());

注意:如果您只想获取有课程的学校并且所有课程都应该有学生,那么您可以使用 Predicate.and() 如下调整过滤器:

.filter(Predicate.not(empty_classes_filter).and(Predicate.not(empty_students_filter)))

编辑:

根据您的评论,使用 Streams API 并不容易做到这一点,因为您遍历学校的集合,并且您只能根据学校的属性过滤学校,而不能过滤他们的属性。所以你需要实现自己的自定义收集器。

我建议分两步解决问题。

第 1 步: 从没有学生的学校中删除所有班级。

第 2 步: 流式传输并收集所有有课程的学校。

//step 1:
result.forEach(school -> {
    List<SchoolClass> school_classes = school.getSchoolClassList();
    List<SchoolClass> empty_classes = 
        school_classes.stream()
                      .filter(school_class -> school_class.getStudentList().isEmpty())
                      .collect(Collectors.toList());
    school.getSchoolClassList().removAll(empty_classes);
});

//step 2:
List<School> remaining_schools = result.stream()
                                       .filter(school -> !school.getSchoolClassList().isEmpty())
                                       .collect(Collectors.toList());

【讨论】:

  • 谢谢你的回答,但在第一个我想过滤班级数组但它仍然根据班级过滤学校数组所以结果并不是我想要的
  • 这里的问题是,如果学校有 3 个班级,其中一个没有学生,它会立即从列表中删除学校,但其他 2 个班级有学生,所以我不想失去他们。这就是为什么过滤应该应用于班级而不是学校,比如不上课没有学生。但我找不到如何:(
  • 我会在大约一个小时后回复你:)
猜你喜欢
  • 1970-01-01
  • 2023-02-11
  • 1970-01-01
  • 2021-07-10
  • 1970-01-01
  • 2019-07-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多