过滤 Java 嵌套列表

Filtering Java Nested List

提问人:ccznyo 提问时间:1/24/2022 最后编辑:ccznyo 更新时间:1/26/2022 访问量:109

问:

我有一个包含班级的学校列表,班级列表也包含学生,学生也是另一个列表。我想应用两个嵌套过滤器,第一个过滤器将检查是否有任何班级有一个空的学生列表,第二个过滤器用于检查学校是否有任何空的班级列表,最后它应该返回列表,但我无法应用两个嵌套过滤器,我不断收到语法错误。我对流 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());
java 列表 过滤 lightweight-stream-api

评论

0赞 f1sh 1/24/2022
只需使用 ,无需流式传输该列表。.filter(cls-> cls.getStudentList().size() > 0)
0赞 ccznyo 1/25/2022
对不起,结果并不是我想要的。我想同时过滤类数组和学校数组。

答:

1赞 edean 1/24/2022 #1

您可能需要添加生成的语法错误。但是,正如我最初看到的,您正在用作标识符,而它实际上是 Java 编程语言中的保留关键字。考虑将标识符重命名为类似的东西。classschoolClass

评论

0赞 ccznyo 1/24/2022
举个例子,首先 anyMatch 方法说无法解析 student 类型中的 getStudentList() 方法。我以示例代码为例,这个任务是我实习的公司交给我的
0赞 motaa 1/24/2022 #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();

然后,您可以在 filter 方法中使用谓词并将它们与 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());

评论

0赞 ccznyo 1/25/2022
谢谢你的回答,但在第一个中,我想过滤类数组,但它仍然根据类过滤学校数组,所以结果不是我真正想要的
0赞 ccznyo 1/25/2022
这里的问题是,如果学校有 3 个班级,其中一个班级没有任何学生,它会立即从列表中删除学校,但其他 2 个班级有学生,所以我不想失去他们。这就是为什么过滤应该应用于班级而不是学校,就像没有班级就没有学生一样。但我找不到如何:(
0赞 motaa 1/25/2022
我会在大约一个小时后回复你:)